! function() {
	this.BH = {
		Views: {},
		Models: {},
		Collections: {},
		Lib: {
			ContextMenus: {}
		},
		Modules: {},
		Templates: {},
		Trackers: {},
		Base: function() {}
	};
	if (typeof onServer !== "undefined" && onServer !== null) {
		module.exports = this.BH
	}
}.call(this);
! function() {
	! function(window, undefined) {
		var TraceKit = {};
		var _oldTraceKit = window.TraceKit;
		var _slice = [].slice;
		var UNKNOWN_FUNCTION = "?";

		function _has(object, key) {
			return Object.prototype.hasOwnProperty.call(object, key)
		}

		function _isUndefined(what) {
			return typeof what === "undefined"
		}
		TraceKit.noConflict = function noConflict() {
			window.TraceKit = _oldTraceKit;
			return TraceKit
		};
		TraceKit.wrap = function traceKitWrapper(func) {
			function wrapped() {
				try {
					return func.apply(this, arguments)
				} catch (e) {
					TraceKit.report(e);
					throw e
				}
			}
			return wrapped
		};
		TraceKit.report = function reportModuleWrapper() {
			var handlers = [],
				lastException = null,
				lastExceptionStack = null;

			function subscribe(handler) {
				installGlobalHandler();
				handlers.push(handler)
			}

			function unsubscribe(handler) {
				for (var i = handlers.length - 1; i >= 0; --i) {
					if (handlers[i] === handler) {
						handlers.splice(i, 1)
					}
				}
			}

			function notifyHandlers(stack, windowError) {
				var exception = null;
				if (windowError && !TraceKit.collectWindowErrors) {
					return
				}
				for (var i in handlers) {
					if (_has(handlers, i)) {
						try {
							handlers[i].apply(null, [stack].concat(_slice.call(arguments, 2)))
						} catch (inner) {
							exception = inner
						}
					}
				}
				if (exception) {
					throw exception
				}
			}
			var _oldOnerrorHandler, _onErrorHandlerInstalled;

			function traceKitWindowOnError(message, url, lineNo) {
				var stack = null;
				if (lastExceptionStack) {
					TraceKit.computeStackTrace.augmentStackTraceWithInitialElement(lastExceptionStack, url, lineNo, message);
					stack = lastExceptionStack;
					lastExceptionStack = null;
					lastException = null
				} else {
					var location = {
						url: url,
						line: lineNo
					};
					location.func = TraceKit.computeStackTrace.guessFunctionName(location.url, location.line);
					location.context = TraceKit.computeStackTrace.gatherContext(location.url, location.line);
					stack = {
						mode: "onerror",
						message: message,
						url: document.location.href,
						stack: [location],
						useragent: navigator.userAgent
					}
				}
				notifyHandlers(stack, "from window.onerror");
				if (_oldOnerrorHandler) {
					return _oldOnerrorHandler.apply(this, arguments)
				}
				return false
			}

			function installGlobalHandler() {
				if (_onErrorHandlerInstalled === true) {
					return
				}
				_oldOnerrorHandler = window.onerror;
				window.onerror = traceKitWindowOnError;
				_onErrorHandlerInstalled = true
			}

			function report(ex) {
				var args = _slice.call(arguments, 1);
				if (lastExceptionStack) {
					if (lastException === ex) {
						return
					} else {
						var s = lastExceptionStack;
						lastExceptionStack = null;
						lastException = null;
						notifyHandlers.apply(null, [s, null].concat(args))
					}
				}
				var stack = TraceKit.computeStackTrace(ex);
				lastExceptionStack = stack;
				lastException = ex;
				window.setTimeout(function() {
					if (lastException === ex) {
						lastExceptionStack = null;
						lastException = null;
						notifyHandlers.apply(null, [stack, null].concat(args))
					}
				}, stack.incomplete ? 2e3 : 0);
				throw ex
			}
			report.subscribe = subscribe;
			report.unsubscribe = unsubscribe;
			return report
		}();
		TraceKit.computeStackTrace = function computeStackTraceWrapper() {
			var debug = false,
				sourceCache = {};

			function loadSource(url) {
				if (!TraceKit.remoteFetching) {
					return ""
				}
				try {
					function getXHR() {
						try {
							return new window.XMLHttpRequest
						} catch (e) {
							return new window.ActiveXObject("Microsoft.XMLHTTP")
						}
					}
					var request = getXHR();
					request.open("GET", url, false);
					request.send("");
					return request.responseText
				} catch (e) {
					return ""
				}
			}

			function getSource(url) {
				if (!_has(sourceCache, url)) {
					var source = "";
					if (url.indexOf(document.domain) !== -1) {
						source = loadSource(url)
					}
					sourceCache[url] = source ? source.split("\n") : []
				}
				return sourceCache[url]
			}

			function guessFunctionName(url, lineNo) {
				var reFunctionArgNames = /function ([^(]*)\(([^)]*)\)/,
					reGuessFunction = /['"]?([0-9A-Za-z$_]+)['"]?\s*[:=]\s*(function|eval|new Function)/,
					line = "",
					maxLines = 10,
					source = getSource(url),
					m;
				if (!source.length) {
					return UNKNOWN_FUNCTION
				}
				for (var i = 0; i < maxLines; ++i) {
					line = source[lineNo - i] + line;
					if (!_isUndefined(line)) {
						if (m = reGuessFunction.exec(line)) {
							return m[1]
						} else if (m = reFunctionArgNames.exec(line)) {
							return m[1]
						}
					}
				}
				return UNKNOWN_FUNCTION
			}

			function gatherContext(url, line) {
				var source = getSource(url);
				if (!source.length) {
					return null
				}
				var context = [],
					linesBefore = Math.floor(TraceKit.linesOfContext / 2),
					linesAfter = linesBefore + TraceKit.linesOfContext % 2,
					start = Math.max(0, line - linesBefore - 1),
					end = Math.min(source.length, line + linesAfter - 1);
				line -= 1;
				for (var i = start; i < end; ++i) {
					if (!_isUndefined(source[i])) {
						context.push(source[i])
					}
				}
				return context.length > 0 ? context : null
			}

			function escapeRegExp(text) {
				return text.replace(/[\-\[\]{}()*+?.,\\\^$|#]/g, "\\$&")
			}

			function escapeCodeAsRegExpForMatchingInsideHTML(body) {
				return escapeRegExp(body).replace("<", "(?:<|&lt;)").replace(">", "(?:>|&gt;)").replace("&", "(?:&|&amp;)").replace('"', '(?:"|&quot;)').replace(/\s+/g, "\\s+")
			}

			function findSourceInUrls(re, urls) {
				var source, m;
				for (var i = 0, j = urls.length; i < j; ++i) {
					if ((source = getSource(urls[i])).length) {
						source = source.join("\n");
						if (m = re.exec(source)) {
							return {
								url: urls[i],
								line: source.substring(0, m.index).split("\n").length,
								column: m.index - source.lastIndexOf("\n", m.index) - 1
							}
						}
					}
				}
				return null
			}

			function findSourceInLine(fragment, url, line) {
				var source = getSource(url),
					re = new RegExp("\\b" + escapeRegExp(fragment) + "\\b"),
					m;
				line -= 1;
				if (source && source.length > line && (m = re.exec(source[line]))) {
					return m.index
				}
				return null
			}

			function findSourceByFunctionBody(func) {
				var urls = [window.location.href],
					scripts = document.getElementsByTagName("script"),
					body, code = "" + func,
					codeRE = /^function(?:\s+([\w$]+))?\s*\(([\w\s,]*)\)\s*\{\s*(\S[\s\S]*\S)\s*\}\s*$/,
					eventRE = /^function on([\w$]+)\s*\(event\)\s*\{\s*(\S[\s\S]*\S)\s*\}\s*$/,
					re, parts, result;
				for (var i = 0; i < scripts.length; ++i) {
					var script = scripts[i];
					if (script.src) {
						urls.push(script.src)
					}
				}
				if (!(parts = codeRE.exec(code))) {
					re = new RegExp(escapeRegExp(code).replace(/\s+/g, "\\s+"))
				} else {
					var name = parts[1] ? "\\s+" + parts[1] : "",
						args = parts[2].split(",").join("\\s*,\\s*");
					body = escapeRegExp(parts[3]).replace(/;$/, ";?");
					re = new RegExp("function" + name + "\\s*\\(\\s*" + args + "\\s*\\)\\s*{\\s*" + body + "\\s*}")
				} if (result = findSourceInUrls(re, urls)) {
					return result
				}
				if (parts = eventRE.exec(code)) {
					var event = parts[1];
					body = escapeCodeAsRegExpForMatchingInsideHTML(parts[2]);
					re = new RegExp("on" + event + "=[\\'\"]\\s*" + body + "\\s*[\\'\"]", "i");
					if (result = findSourceInUrls(re, urls[0])) {
						return result
					}
					re = new RegExp(body);
					if (result = findSourceInUrls(re, urls)) {
						return result
					}
				}
				return null
			}

			function computeStackTraceFromStackProp(ex) {
				if (!ex.stack) {
					return null
				}
				var chrome = /^\s*at (?:((?:\[object object\])?\S+(?: \[as \S+\])?) )?\(?((?:file|http|https):.*?):(\d+)(?::(\d+))?\)?\s*$/i,
					gecko = /^\s*(\S*)(?:\((.*?)\))?@((?:file|http|https).*?):(\d+)(?::(\d+))?\s*$/i,
					lines = ex.stack.split("\n"),
					stack = [],
					parts, element, reference = /^(.*) is undefined$/.exec(ex.message);
				for (var i = 0, j = lines.length; i < j; ++i) {
					if (parts = gecko.exec(lines[i])) {
						element = {
							url: parts[3],
							func: parts[1] || UNKNOWN_FUNCTION,
							args: parts[2] ? parts[2].split(",") : "",
							line: +parts[4],
							column: parts[5] ? +parts[5] : null
						}
					} else if (parts = chrome.exec(lines[i])) {
						element = {
							url: parts[2],
							func: parts[1] || UNKNOWN_FUNCTION,
							line: +parts[3],
							column: parts[4] ? +parts[4] : null
						}
					} else {
						continue
					} if (!element.func && element.line) {
						element.func = guessFunctionName(element.url, element.line)
					}
					if (element.line) {
						element.context = gatherContext(element.url, element.line)
					}
					stack.push(element)
				}
				if (stack[0] && stack[0].line && !stack[0].column && reference) {
					stack[0].column = findSourceInLine(reference[1], stack[0].url, stack[0].line)
				}
				if (!stack.length) {
					return null
				}
				return {
					mode: "stack",
					name: ex.name,
					message: ex.message,
					url: document.location.href,
					stack: stack,
					useragent: navigator.userAgent
				}
			}

			function computeStackTraceFromStacktraceProp(ex) {
				var stacktrace = ex.stacktrace;
				var testRE = / line (\d+), column (\d+) in (?:<anonymous function: ([^>]+)>|([^\)]+))\((.*)\) in (.*):\s*$/i,
					lines = stacktrace.split("\n"),
					stack = [],
					parts;
				for (var i = 0, j = lines.length; i < j; i += 2) {
					if (parts = testRE.exec(lines[i])) {
						var element = {
							line: +parts[1],
							column: +parts[2],
							func: parts[3] || parts[4],
							args: parts[5] ? parts[5].split(",") : [],
							url: parts[6]
						};
						if (!element.func && element.line) {
							element.func = guessFunctionName(element.url, element.line)
						}
						if (element.line) {
							try {
								element.context = gatherContext(element.url, element.line)
							} catch (exc) {}
						}
						if (!element.context) {
							element.context = [lines[i + 1]]
						}
						stack.push(element)
					}
				}
				if (!stack.length) {
					return null
				}
				return {
					mode: "stacktrace",
					name: ex.name,
					message: ex.message,
					url: document.location.href,
					stack: stack,
					useragent: navigator.userAgent
				}
			}

			function computeStackTraceFromOperaMultiLineMessage(ex) {
				var lines = ex.message.split("\n");
				if (lines.length < 4) {
					return null
				}
				var lineRE1 = /^\s*Line (\d+) of linked script ((?:file|http|https)\S+)(?:: in function (\S+))?\s*$/i,
					lineRE2 = /^\s*Line (\d+) of inline#(\d+) script in ((?:file|http|https)\S+)(?:: in function (\S+))?\s*$/i,
					lineRE3 = /^\s*Line (\d+) of function script\s*$/i,
					stack = [],
					scripts = document.getElementsByTagName("script"),
					inlineScriptBlocks = [],
					parts, i, len, source;
				for (i in scripts) {
					if (_has(scripts, i) && !scripts[i].src) {
						inlineScriptBlocks.push(scripts[i])
					}
				}
				for (i = 2, len = lines.length; i < len; i += 2) {
					var item = null;
					if (parts = lineRE1.exec(lines[i])) {
						item = {
							url: parts[2],
							func: parts[3],
							line: +parts[1]
						}
					} else if (parts = lineRE2.exec(lines[i])) {
						item = {
							url: parts[3],
							func: parts[4]
						};
						var relativeLine = +parts[1];
						var script = inlineScriptBlocks[parts[2] - 1];
						if (script) {
							source = getSource(item.url);
							if (source) {
								source = source.join("\n");
								var pos = source.indexOf(script.innerText);
								if (pos >= 0) {
									item.line = relativeLine + source.substring(0, pos).split("\n").length
								}
							}
						}
					} else if (parts = lineRE3.exec(lines[i])) {
						var url = window.location.href.replace(/#.*$/, ""),
							line = parts[1];
						var re = new RegExp(escapeCodeAsRegExpForMatchingInsideHTML(lines[i + 1]));
						source = findSourceInUrls(re, [url]);
						item = {
							url: url,
							line: source ? source.line : line,
							func: ""
						}
					}
					if (item) {
						if (!item.func) {
							item.func = guessFunctionName(item.url, item.line)
						}
						var context = gatherContext(item.url, item.line);
						var midline = context ? context[Math.floor(context.length / 2)] : null;
						if (context && midline.replace(/^\s*/, "") === lines[i + 1].replace(/^\s*/, "")) {
							item.context = context
						} else {
							item.context = [lines[i + 1]]
						}
						stack.push(item)
					}
				}
				if (!stack.length) {
					return null
				}
				return {
					mode: "multiline",
					name: ex.name,
					message: lines[0],
					url: document.location.href,
					stack: stack,
					useragent: navigator.userAgent
				}
			}

			function augmentStackTraceWithInitialElement(stackInfo, url, lineNo, message) {
				var initial = {
					url: url,
					line: lineNo
				};
				if (initial.url && initial.line) {
					stackInfo.incomplete = false;
					if (!initial.func) {
						initial.func = guessFunctionName(initial.url, initial.line)
					}
					if (!initial.context) {
						initial.context = gatherContext(initial.url, initial.line)
					}
					var reference = / '([^']+)' /.exec(message);
					if (reference) {
						initial.column = findSourceInLine(reference[1], initial.url, initial.line)
					}
					if (stackInfo.stack.length > 0) {
						if (stackInfo.stack[0].url === initial.url) {
							if (stackInfo.stack[0].line === initial.line) {
								return false
							} else if (!stackInfo.stack[0].line && stackInfo.stack[0].func === initial.func) {
								stackInfo.stack[0].line = initial.line;
								stackInfo.stack[0].context = initial.context;
								return false
							}
						}
					}
					stackInfo.stack.unshift(initial);
					stackInfo.partial = true;
					return true
				} else {
					stackInfo.incomplete = true
				}
				return false
			}

			function computeStackTraceByWalkingCallerChain(ex, depth) {
				var functionName = /function\s+([_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*)?\s*\(/i,
					stack = [],
					funcs = {}, recursion = false,
					parts, item, source;
				for (var curr = computeStackTraceByWalkingCallerChain.caller; curr && !recursion; curr = curr.caller) {
					if (curr === computeStackTrace || curr === TraceKit.report) {
						continue
					}
					item = {
						url: null,
						func: UNKNOWN_FUNCTION,
						line: null,
						column: null
					};
					if (curr.name) {
						item.func = curr.name
					} else if (parts = functionName.exec(curr.toString())) {
						item.func = parts[1]
					}
					if (source = findSourceByFunctionBody(curr)) {
						item.url = source.url;
						item.line = source.line;
						if (item.func === UNKNOWN_FUNCTION) {
							item.func = guessFunctionName(item.url, item.line)
						}
						var reference = / '([^']+)' /.exec(ex.message || ex.description);
						if (reference) {
							item.column = findSourceInLine(reference[1], source.url, source.line)
						}
					}
					if (funcs["" + curr]) {
						recursion = true
					} else {
						funcs["" + curr] = true
					}
					stack.push(item)
				}
				if (depth) {
					stack.splice(0, depth)
				}
				var result = {
					mode: "callers",
					name: ex.name,
					message: ex.message,
					url: document.location.href,
					stack: stack,
					useragent: navigator.userAgent
				};
				augmentStackTraceWithInitialElement(result, ex.sourceURL || ex.fileName, ex.line || ex.lineNumber, ex.message || ex.description);
				return result
			}

			function computeStackTrace(ex, depth) {
				var stack = null;
				depth = depth == null ? 0 : +depth;
				try {
					stack = computeStackTraceFromStacktraceProp(ex);
					if (stack) {
						return stack
					}
				} catch (e) {
					if (debug) {
						throw e
					}
				}
				try {
					stack = computeStackTraceFromStackProp(ex);
					if (stack) {
						return stack
					}
				} catch (e) {
					if (debug) {
						throw e
					}
				}
				try {
					stack = computeStackTraceFromOperaMultiLineMessage(ex);
					if (stack) {
						return stack
					}
				} catch (e) {
					if (debug) {
						throw e
					}
				}
				try {
					stack = computeStackTraceByWalkingCallerChain(ex, depth + 1);
					if (stack) {
						return stack
					}
				} catch (e) {
					if (debug) {
						throw e
					}
				}
				return {
					mode: "failed"
				}
			}

			function computeStackTraceOfCaller(depth) {
				depth = (depth == null ? 0 : +depth) + 1;
				try {
					throw new Error
				} catch (ex) {
					return computeStackTrace(ex, depth + 1)
				}
				return null
			}
			computeStackTrace.augmentStackTraceWithInitialElement = augmentStackTraceWithInitialElement;
			computeStackTrace.guessFunctionName = guessFunctionName;
			computeStackTrace.gatherContext = gatherContext;
			computeStackTrace.ofCaller = computeStackTraceOfCaller;
			return computeStackTrace
		}();
		! function extendToAsynchronousCallbacks() {
			var _helper = function _helper(fnName) {
				var originalFn = window[fnName];
				window[fnName] = function traceKitAsyncExtension() {
					var args = _slice.call(arguments);
					var originalCallback = args[0];
					if (typeof originalCallback === "function") {
						args[0] = TraceKit.wrap(originalCallback)
					}
					if (originalFn.apply) {
						return originalFn.apply(this, args)
					} else {
						return originalFn(args[0], args[1])
					}
				}
			};
			_helper("setTimeout");
			_helper("setInterval")
		}();
		if (!TraceKit.remoteFetching) {
			TraceKit.remoteFetching = true
		}
		if (!TraceKit.collectWindowErrors) {
			TraceKit.collectWindowErrors = true
		}
		if (!TraceKit.linesOfContext || TraceKit.linesOfContext < 1) {
			TraceKit.linesOfContext = 11
		}
		window.TraceKit = TraceKit
	}(window);
	var Notice;
	Notice = function() {
		function Notice(options) {
			var k, v, _ref, _ref1, _ref2, _ref3, _ref4;
			this.options = options != null ? options : {};
			this.stackInfo = this.options.stackInfo || this.options.error && TraceKit.computeStackTrace(this.options.error);
			this.trace = this._parseBacktrace((_ref = this.stackInfo) != null ? _ref.stack : void 0);
			this["class"] = (_ref1 = this.stackInfo) != null ? _ref1.name : void 0;
			this.message = (_ref2 = this.stackInfo) != null ? _ref2.message : void 0;
			this.source = this.stackInfo && this._extractSource(this.stackInfo.stack);
			this.url = document.URL;
			this.project_root = Honeybadger.configuration.project_root;
			this.environment = Honeybadger.configuration.environment;
			this.component = Honeybadger.configuration.component;
			this.action = Honeybadger.configuration.action;
			this.context = {};
			_ref3 = Honeybadger.context;
			for (k in _ref3) {
				v = _ref3[k];
				this.context[k] = v
			}
			if (this.options.context) {
				_ref4 = this.options.context;
				for (k in _ref4) {
					v = _ref4[k];
					this.context[k] = v
				}
			}
		}
		Notice.prototype.toJSON = function() {
			return JSON.stringify({
				notifier: {
					name: "honeybadger.js",
					url: "https://github.com/honeybadger-io/honeybadger-js",
					version: Honeybadger.version,
					language: "javascript"
				},
				error: {
					"class": this["class"],
					message: this.message,
					backtrace: this.trace,
					source: this.source
				},
				request: {
					url: this.url,
					component: this.component,
					action: this.action,
					context: this.context,
					cgi_data: this._cgiData()
				},
				server: {
					project_root: this.project_root,
					environment_name: this.environment
				}
			})
		};
		Notice.prototype._parseBacktrace = function(stack) {
			var backtrace, trace, _i, _len, _ref, _ref1;
			if (stack == null) {
				stack = []
			}
			backtrace = [];
			for (_i = 0, _len = stack.length; _i < _len; _i++) {
				trace = stack[_i];
				if ((_ref = trace.url) != null ? _ref.match(/honeybadger(?:\.min)?\.js/) : void 0) {
					continue
				}
				backtrace.push({
					file: ((_ref1 = trace.url) != null ? _ref1.replace(Honeybadger.configuration.project_root, "[PROJECT_ROOT]") : void 0) || "unknown",
					number: trace.line,
					method: trace.func
				})
			}
			return backtrace
		};
		Notice.prototype._extractSource = function(stack) {
			var i, line, source, _i, _len, _ref, _ref1, _ref2;
			if (stack == null) {
				stack = []
			}
			source = {};
			_ref2 = (_ref = (_ref1 = stack[0]) != null ? _ref1.context : void 0) != null ? _ref : [];
			for (i = _i = 0, _len = _ref2.length; _i < _len; i = ++_i) {
				line = _ref2[i];
				source[i] = line
			}
			return source
		};
		Notice.prototype._cgiData = function() {
			var data, k, v;
			data = {};
			for (k in navigator) {
				v = navigator[k];
				if (typeof v !== "object") {
					data[k.split(/(?=[A-Z][a-z]*)/).join("_").toUpperCase()] = v
				}
			}
			data["HTTP_USER_AGENT"] = data["USER_AGENT"];
			delete data["USER_AGENT"];
			if (document.referrer.match(/\S/)) {
				data["HTTP_REFERER"] = document.referrer
			}
			return data
		};
		return Notice
	}();
	var Honeybadger;
	Honeybadger = function() {
		var _this = this;

		function Honeybadger() {}
		Honeybadger.version = "0.0.2";
		Honeybadger.default_configuration = {
			api_key: null,
			host: "api.honeybadger.io",
			ssl: true,
			project_root: window.location.protocol + "//" + window.location.host,
			environment: "production",
			component: null,
			action: null,
			disabled: true,
			onerror: false
		};
		Honeybadger.configured = false;
		Honeybadger.configure = function(options) {
			var k, v;
			if (options == null) {
				options = {}
			}
			if (this.configured === false) {
				if (typeof options.disabled === "undefined") {
					options["disabled"] = false
				}
				this.configured = true
			}
			for (k in options) {
				v = options[k];
				this.configuration[k] = v
			}
			TraceKit.collectWindowErrors = this.configuration.onerror;
			return this
		};
		Honeybadger.configuration = {
			reset: function() {
				var k, v, _ref;
				Honeybadger.configured = false;
				_ref = Honeybadger.default_configuration;
				for (k in _ref) {
					v = _ref[k];
					Honeybadger.configuration[k] = v
				}
				TraceKit.collectWindowErrors = Honeybadger.configuration.onerror;
				return Honeybadger
			}
		};
		Honeybadger.configuration.reset();
		Honeybadger.context = {};
		Honeybadger.resetContext = function(options) {
			if (options == null) {
				options = {}
			}
			this.context = options;
			return this
		};
		Honeybadger.setContext = function(options) {
			var k, v;
			if (options == null) {
				options = {}
			}
			for (k in options) {
				v = options[k];
				this.context[k] = v
			}
			return this
		};
		Honeybadger.notify = function(error, options) {
			var notice;
			if (options == null) {
				options = {}
			}
			if (this.configuration.disabled === true) {
				return false
			}
			if (error) {
				options["error"] = error
			}
			notice = new Notice(options);
			return this._sendRequest(notice.toJSON())
		};
		Honeybadger._sendRequest = function(data) {
			var url;
			url = "http" + (this.configuration.ssl && "s" || "") + "://" + this.configuration.host + "/v1/notices.html";
			return this._crossDomainPost(url, data)
		};
		Honeybadger._crossDomainPost = function(url, payload) {
			var form, iframe, input, uniqueNameOfFrame;
			iframe = document.createElement("iframe");
			uniqueNameOfFrame = "_hb_" + (new Date).getTime();
			document.body.appendChild(iframe);
			iframe.style.display = "none";
			iframe.contentWindow.name = uniqueNameOfFrame;
			form = document.createElement("form");
			form.target = uniqueNameOfFrame;
			form.action = url;
			form.method = "POST";
			input = document.createElement("input");
			input.type = "hidden";
			input.name = "payload";
			input.value = payload;
			form.appendChild(input);
			input = document.createElement("input");
			input.type = "hidden";
			input.name = "api_key";
			input.value = this.configuration.api_key;
			form.appendChild(input);
			document.body.appendChild(form);
			return form.submit()
		};
		Honeybadger._handleTraceKitSubscription = function(stackInfo) {
			return Honeybadger.notify(null, {
				stackInfo: stackInfo
			})
		};
		return Honeybadger
	}.call(this);
	TraceKit.report.subscribe(Honeybadger._handleTraceKitSubscription);
	(typeof exports !== "undefined" && exports !== null ? exports : this).Honeybadger = Honeybadger
}.call(this);
! function() {
	var root = this;
	var previousUnderscore = root._;
	var breaker = {};
	var ArrayProto = Array.prototype,
		ObjProto = Object.prototype,
		FuncProto = Function.prototype;
	var push = ArrayProto.push,
		slice = ArrayProto.slice,
		concat = ArrayProto.concat,
		toString = ObjProto.toString,
		hasOwnProperty = ObjProto.hasOwnProperty;
	var nativeForEach = ArrayProto.forEach,
		nativeMap = ArrayProto.map,
		nativeReduce = ArrayProto.reduce,
		nativeReduceRight = ArrayProto.reduceRight,
		nativeFilter = ArrayProto.filter,
		nativeEvery = ArrayProto.every,
		nativeSome = ArrayProto.some,
		nativeIndexOf = ArrayProto.indexOf,
		nativeLastIndexOf = ArrayProto.lastIndexOf,
		nativeIsArray = Array.isArray,
		nativeKeys = Object.keys,
		nativeBind = FuncProto.bind;
	var _ = function(obj) {
		if (obj instanceof _) return obj;
		if (!(this instanceof _)) return new _(obj);
		this._wrapped = obj
	};
	if (typeof exports !== "undefined") {
		if (typeof module !== "undefined" && module.exports) {
			exports = module.exports = _
		}
		exports._ = _
	} else {
		root._ = _
	}
	_.VERSION = "1.4.3";
	var each = _.each = _.forEach = function(obj, iterator, context) {
		if (obj == null) return;
		if (nativeForEach && obj.forEach === nativeForEach) {
			obj.forEach(iterator, context)
		} else if (obj.length === +obj.length) {
			for (var i = 0, l = obj.length; i < l; i++) {
				if (iterator.call(context, obj[i], i, obj) === breaker) return
			}
		} else {
			for (var key in obj) {
				if (_.has(obj, key)) {
					if (iterator.call(context, obj[key], key, obj) === breaker) return
				}
			}
		}
	};
	_.map = _.collect = function(obj, iterator, context) {
		var results = [];
		if (obj == null) return results;
		if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
		each(obj, function(value, index, list) {
			results[results.length] = iterator.call(context, value, index, list)
		});
		return results
	};
	var reduceError = "Reduce of empty array with no initial value";
	_.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
		var initial = arguments.length > 2;
		if (obj == null) obj = [];
		if (nativeReduce && obj.reduce === nativeReduce) {
			if (context) iterator = _.bind(iterator, context);
			return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator)
		}
		each(obj, function(value, index, list) {
			if (!initial) {
				memo = value;
				initial = true
			} else {
				memo = iterator.call(context, memo, value, index, list)
			}
		});
		if (!initial) throw new TypeError(reduceError);
		return memo
	};
	_.reduceRight = _.foldr = function(obj, iterator, memo, context) {
		var initial = arguments.length > 2;
		if (obj == null) obj = [];
		if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
			if (context) iterator = _.bind(iterator, context);
			return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator)
		}
		var length = obj.length;
		if (length !== +length) {
			var keys = _.keys(obj);
			length = keys.length
		}
		each(obj, function(value, index, list) {
			index = keys ? keys[--length] : --length;
			if (!initial) {
				memo = obj[index];
				initial = true
			} else {
				memo = iterator.call(context, memo, obj[index], index, list)
			}
		});
		if (!initial) throw new TypeError(reduceError);
		return memo
	};
	_.find = _.detect = function(obj, iterator, context) {
		var result;
		any(obj, function(value, index, list) {
			if (iterator.call(context, value, index, list)) {
				result = value;
				return true
			}
		});
		return result
	};
	_.filter = _.select = function(obj, iterator, context) {
		var results = [];
		if (obj == null) return results;
		if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
		each(obj, function(value, index, list) {
			if (iterator.call(context, value, index, list)) results[results.length] = value
		});
		return results
	};
	_.reject = function(obj, iterator, context) {
		return _.filter(obj, function(value, index, list) {
			return !iterator.call(context, value, index, list)
		}, context)
	};
	_.every = _.all = function(obj, iterator, context) {
		iterator || (iterator = _.identity);
		var result = true;
		if (obj == null) return result;
		if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
		each(obj, function(value, index, list) {
			if (!(result = result && iterator.call(context, value, index, list))) return breaker
		});
		return !!result
	};
	var any = _.some = _.any = function(obj, iterator, context) {
		iterator || (iterator = _.identity);
		var result = false;
		if (obj == null) return result;
		if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
		each(obj, function(value, index, list) {
			if (result || (result = iterator.call(context, value, index, list))) return breaker
		});
		return !!result
	};
	_.contains = _.include = function(obj, target) {
		if (obj == null) return false;
		if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
		return any(obj, function(value) {
			return value === target
		})
	};
	_.invoke = function(obj, method) {
		var args = slice.call(arguments, 2);
		return _.map(obj, function(value) {
			return (_.isFunction(method) ? method : value[method]).apply(value, args)
		})
	};
	_.pluck = function(obj, key) {
		return _.map(obj, function(value) {
			return value[key]
		})
	};
	_.where = function(obj, attrs) {
		if (_.isEmpty(attrs)) return [];
		return _.filter(obj, function(value) {
			for (var key in attrs) {
				if (attrs[key] !== value[key]) return false
			}
			return true
		})
	};
	_.max = function(obj, iterator, context) {
		if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
			return Math.max.apply(Math, obj)
		}
		if (!iterator && _.isEmpty(obj)) return -Infinity;
		var result = {
			computed: -Infinity,
			value: -Infinity
		};
		each(obj, function(value, index, list) {
			var computed = iterator ? iterator.call(context, value, index, list) : value;
			computed >= result.computed && (result = {
				value: value,
				computed: computed
			})
		});
		return result.value
	};
	_.min = function(obj, iterator, context) {
		if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
			return Math.min.apply(Math, obj)
		}
		if (!iterator && _.isEmpty(obj)) return Infinity;
		var result = {
			computed: Infinity,
			value: Infinity
		};
		each(obj, function(value, index, list) {
			var computed = iterator ? iterator.call(context, value, index, list) : value;
			computed < result.computed && (result = {
				value: value,
				computed: computed
			})
		});
		return result.value
	};
	_.shuffle = function(obj) {
		var rand;
		var index = 0;
		var shuffled = [];
		each(obj, function(value) {
			rand = _.random(index++);
			shuffled[index - 1] = shuffled[rand];
			shuffled[rand] = value
		});
		return shuffled
	};
	var lookupIterator = function(value) {
		return _.isFunction(value) ? value : function(obj) {
			return obj[value]
		}
	};
	_.sortBy = function(obj, value, context) {
		var iterator = lookupIterator(value);
		return _.pluck(_.map(obj, function(value, index, list) {
			return {
				value: value,
				index: index,
				criteria: iterator.call(context, value, index, list)
			}
		}).sort(function(left, right) {
			var a = left.criteria;
			var b = right.criteria;
			if (a !== b) {
				if (a > b || a === void 0) return 1;
				if (a < b || b === void 0) return -1
			}
			return left.index < right.index ? -1 : 1
		}), "value")
	};
	var group = function(obj, value, context, behavior) {
		var result = {};
		var iterator = lookupIterator(value || _.identity);
		each(obj, function(value, index) {
			var key = iterator.call(context, value, index, obj);
			behavior(result, key, value)
		});
		return result
	};
	_.groupBy = function(obj, value, context) {
		return group(obj, value, context, function(result, key, value) {
			(_.has(result, key) ? result[key] : result[key] = []).push(value)
		})
	};
	_.countBy = function(obj, value, context) {
		return group(obj, value, context, function(result, key) {
			if (!_.has(result, key)) result[key] = 0;
			result[key]++
		})
	};
	_.sortedIndex = function(array, obj, iterator, context) {
		iterator = iterator == null ? _.identity : lookupIterator(iterator);
		var value = iterator.call(context, obj);
		var low = 0,
			high = array.length;
		while (low < high) {
			var mid = low + high >>> 1;
			iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid
		}
		return low
	};
	_.toArray = function(obj) {
		if (!obj) return [];
		if (_.isArray(obj)) return slice.call(obj);
		if (obj.length === +obj.length) return _.map(obj, _.identity);
		return _.values(obj)
	};
	_.size = function(obj) {
		if (obj == null) return 0;
		return obj.length === +obj.length ? obj.length : _.keys(obj).length
	};
	_.first = _.head = _.take = function(array, n, guard) {
		if (array == null) return void 0;
		return n != null && !guard ? slice.call(array, 0, n) : array[0]
	};
	_.initial = function(array, n, guard) {
		return slice.call(array, 0, array.length - (n == null || guard ? 1 : n))
	};
	_.last = function(array, n, guard) {
		if (array == null) return void 0;
		if (n != null && !guard) {
			return slice.call(array, Math.max(array.length - n, 0))
		} else {
			return array[array.length - 1]
		}
	};
	_.rest = _.tail = _.drop = function(array, n, guard) {
		return slice.call(array, n == null || guard ? 1 : n)
	};
	_.compact = function(array) {
		return _.filter(array, _.identity)
	};
	var flatten = function(input, shallow, output) {
		each(input, function(value) {
			if (_.isArray(value)) {
				shallow ? push.apply(output, value) : flatten(value, shallow, output)
			} else {
				output.push(value)
			}
		});
		return output
	};
	_.flatten = function(array, shallow) {
		return flatten(array, shallow, [])
	};
	_.without = function(array) {
		return _.difference(array, slice.call(arguments, 1))
	};
	_.uniq = _.unique = function(array, isSorted, iterator, context) {
		if (_.isFunction(isSorted)) {
			context = iterator;
			iterator = isSorted;
			isSorted = false
		}
		var initial = iterator ? _.map(array, iterator, context) : array;
		var results = [];
		var seen = [];
		each(initial, function(value, index) {
			if (isSorted ? !index || seen[seen.length - 1] !== value : !_.contains(seen, value)) {
				seen.push(value);
				results.push(array[index])
			}
		});
		return results
	};
	_.union = function() {
		return _.uniq(concat.apply(ArrayProto, arguments))
	};
	_.intersection = function(array) {
		var rest = slice.call(arguments, 1);
		return _.filter(_.uniq(array), function(item) {
			return _.every(rest, function(other) {
				return _.indexOf(other, item) >= 0
			})
		})
	};
	_.difference = function(array) {
		var rest = concat.apply(ArrayProto, slice.call(arguments, 1));
		return _.filter(array, function(value) {
			return !_.contains(rest, value)
		})
	};
	_.zip = function() {
		var args = slice.call(arguments);
		var length = _.max(_.pluck(args, "length"));
		var results = new Array(length);
		for (var i = 0; i < length; i++) {
			results[i] = _.pluck(args, "" + i)
		}
		return results
	};
	_.object = function(list, values) {
		if (list == null) return {};
		var result = {};
		for (var i = 0, l = list.length; i < l; i++) {
			if (values) {
				result[list[i]] = values[i]
			} else {
				result[list[i][0]] = list[i][1]
			}
		}
		return result
	};
	_.indexOf = function(array, item, isSorted) {
		if (array == null) return -1;
		var i = 0,
			l = array.length;
		if (isSorted) {
			if (typeof isSorted == "number") {
				i = isSorted < 0 ? Math.max(0, l + isSorted) : isSorted
			} else {
				i = _.sortedIndex(array, item);
				return array[i] === item ? i : -1
			}
		}
		if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted);
		for (; i < l; i++)
			if (array[i] === item) return i;
		return -1
	};
	_.lastIndexOf = function(array, item, from) {
		if (array == null) return -1;
		var hasIndex = from != null;
		if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) {
			return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item)
		}
		var i = hasIndex ? from : array.length;
		while (i--)
			if (array[i] === item) return i;
		return -1
	};
	_.range = function(start, stop, step) {
		if (arguments.length <= 1) {
			stop = start || 0;
			start = 0
		}
		step = arguments[2] || 1;
		var len = Math.max(Math.ceil((stop - start) / step), 0);
		var idx = 0;
		var range = new Array(len);
		while (idx < len) {
			range[idx++] = start;
			start += step
		}
		return range
	};
	var ctor = function() {};
	_.bind = function(func, context) {
		var args, bound;
		if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
		if (!_.isFunction(func)) throw new TypeError;
		args = slice.call(arguments, 2);
		return bound = function() {
			if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments)));
			ctor.prototype = func.prototype;
			var self = new ctor;
			ctor.prototype = null;
			var result = func.apply(self, args.concat(slice.call(arguments)));
			if (Object(result) === result) return result;
			return self
		}
	};
	_.bindAll = function(obj) {
		var funcs = slice.call(arguments, 1);
		if (funcs.length == 0) funcs = _.functions(obj);
		each(funcs, function(f) {
			obj[f] = _.bind(obj[f], obj)
		});
		return obj
	};
	_.memoize = function(func, hasher) {
		var memo = {};
		hasher || (hasher = _.identity);
		return function() {
			var key = hasher.apply(this, arguments);
			return _.has(memo, key) ? memo[key] : memo[key] = func.apply(this, arguments)
		}
	};
	_.delay = function(func, wait) {
		var args = slice.call(arguments, 2);
		return setTimeout(function() {
			return func.apply(null, args)
		}, wait)
	};
	_.defer = function(func) {
		return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)))
	};
	_.throttle = function(func, wait) {
		var context, args, timeout, result;
		var previous = 0;
		var later = function() {
			previous = new Date;
			timeout = null;
			result = func.apply(context, args)
		};
		return function() {
			var now = new Date;
			var remaining = wait - (now - previous);
			context = this;
			args = arguments;
			if (remaining <= 0) {
				clearTimeout(timeout);
				timeout = null;
				previous = now;
				result = func.apply(context, args)
			} else if (!timeout) {
				timeout = setTimeout(later, remaining)
			}
			return result
		}
	};
	_.debounce = function(func, wait, immediate) {
		var timeout, result;
		return function() {
			var context = this,
				args = arguments;
			var later = function() {
				timeout = null;
				if (!immediate) result = func.apply(context, args)
			};
			var callNow = immediate && !timeout;
			clearTimeout(timeout);
			timeout = setTimeout(later, wait);
			if (callNow) result = func.apply(context, args);
			return result
		}
	};
	_.once = function(func) {
		var ran = false,
			memo;
		return function() {
			if (ran) return memo;
			ran = true;
			memo = func.apply(this, arguments);
			func = null;
			return memo
		}
	};
	_.wrap = function(func, wrapper) {
		return function() {
			var args = [func];
			push.apply(args, arguments);
			return wrapper.apply(this, args)
		}
	};
	_.compose = function() {
		var funcs = arguments;
		return function() {
			var args = arguments;
			for (var i = funcs.length - 1; i >= 0; i--) {
				args = [funcs[i].apply(this, args)]
			}
			return args[0]
		}
	};
	_.after = function(times, func) {
		if (times <= 0) return func();
		return function() {
			if (--times < 1) {
				return func.apply(this, arguments)
			}
		}
	};
	_.keys = nativeKeys || function(obj) {
		if (obj !== Object(obj)) throw new TypeError("Invalid object");
		var keys = [];
		for (var key in obj)
			if (_.has(obj, key)) keys[keys.length] = key;
		return keys
	};
	_.values = function(obj) {
		var values = [];
		for (var key in obj)
			if (_.has(obj, key)) values.push(obj[key]);
		return values
	};
	_.pairs = function(obj) {
		var pairs = [];
		for (var key in obj)
			if (_.has(obj, key)) pairs.push([key, obj[key]]);
		return pairs
	};
	_.invert = function(obj) {
		var result = {};
		for (var key in obj)
			if (_.has(obj, key)) result[obj[key]] = key;
		return result
	};
	_.functions = _.methods = function(obj) {
		var names = [];
		for (var key in obj) {
			if (_.isFunction(obj[key])) names.push(key)
		}
		return names.sort()
	};
	_.extend = function(obj) {
		each(slice.call(arguments, 1), function(source) {
			if (source) {
				for (var prop in source) {
					obj[prop] = source[prop]
				}
			}
		});
		return obj
	};
	_.pick = function(obj) {
		var copy = {};
		var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
		each(keys, function(key) {
			if (key in obj) copy[key] = obj[key]
		});
		return copy
	};
	_.omit = function(obj) {
		var copy = {};
		var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
		for (var key in obj) {
			if (!_.contains(keys, key)) copy[key] = obj[key]
		}
		return copy
	};
	_.defaults = function(obj) {
		each(slice.call(arguments, 1), function(source) {
			if (source) {
				for (var prop in source) {
					if (obj[prop] == null) obj[prop] = source[prop]
				}
			}
		});
		return obj
	};
	_.clone = function(obj) {
		if (!_.isObject(obj)) return obj;
		return _.isArray(obj) ? obj.slice() : _.extend({}, obj)
	};
	_.tap = function(obj, interceptor) {
		interceptor(obj);
		return obj
	};
	var eq = function(a, b, aStack, bStack) {
		if (a === b) return a !== 0 || 1 / a == 1 / b;
		if (a == null || b == null) return a === b;
		if (a instanceof _) a = a._wrapped;
		if (b instanceof _) b = b._wrapped;
		var className = toString.call(a);
		if (className != toString.call(b)) return false;
		switch (className) {
			case "[object String]":
				return a == String(b);
			case "[object Number]":
				return a != +a ? b != +b : a == 0 ? 1 / a == 1 / b : a == +b;
			case "[object Date]":
			case "[object Boolean]":
				return +a == +b;
			case "[object RegExp]":
				return a.source == b.source && a.global == b.global && a.multiline == b.multiline && a.ignoreCase == b.ignoreCase
		}
		if (typeof a != "object" || typeof b != "object") return false;
		var length = aStack.length;
		while (length--) {
			if (aStack[length] == a) return bStack[length] == b
		}
		aStack.push(a);
		bStack.push(b);
		var size = 0,
			result = true;
		if (className == "[object Array]") {
			size = a.length;
			result = size == b.length;
			if (result) {
				while (size--) {
					if (!(result = eq(a[size], b[size], aStack, bStack))) break
				}
			}
		} else {
			var aCtor = a.constructor,
				bCtor = b.constructor;
			if (aCtor !== bCtor && !(_.isFunction(aCtor) && aCtor instanceof aCtor && _.isFunction(bCtor) && bCtor instanceof bCtor)) {
				return false
			}
			for (var key in a) {
				if (_.has(a, key)) {
					size++;
					if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break
				}
			}
			if (result) {
				for (key in b) {
					if (_.has(b, key) && !size--) break
				}
				result = !size
			}
		}
		aStack.pop();
		bStack.pop();
		return result
	};
	_.isEqual = function(a, b) {
		return eq(a, b, [], [])
	};
	_.isEmpty = function(obj) {
		if (obj == null) return true;
		if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
		for (var key in obj)
			if (_.has(obj, key)) return false;
		return true
	};
	_.isElement = function(obj) {
		return !!(obj && obj.nodeType === 1)
	};
	_.isArray = nativeIsArray || function(obj) {
		return toString.call(obj) == "[object Array]"
	};
	_.isObject = function(obj) {
		return obj === Object(obj)
	};
	each(["Arguments", "Function", "String", "Number", "Date", "RegExp"], function(name) {
		_["is" + name] = function(obj) {
			return toString.call(obj) == "[object " + name + "]"
		}
	});
	if (!_.isArguments(arguments)) {
		_.isArguments = function(obj) {
			return !!(obj && _.has(obj, "callee"))
		}
	}
	if (typeof / . / !== "function") {
		_.isFunction = function(obj) {
			return typeof obj === "function"
		}
	}
	_.isFinite = function(obj) {
		return isFinite(obj) && !isNaN(parseFloat(obj))
	};
	_.isNaN = function(obj) {
		return _.isNumber(obj) && obj != +obj
	};
	_.isBoolean = function(obj) {
		return obj === true || obj === false || toString.call(obj) == "[object Boolean]"
	};
	_.isNull = function(obj) {
		return obj === null
	};
	_.isUndefined = function(obj) {
		return obj === void 0
	};
	_.has = function(obj, key) {
		return hasOwnProperty.call(obj, key)
	};
	_.noConflict = function() {
		root._ = previousUnderscore;
		return this
	};
	_.identity = function(value) {
		return value
	};
	_.times = function(n, iterator, context) {
		var accum = Array(n);
		for (var i = 0; i < n; i++) accum[i] = iterator.call(context, i);
		return accum
	};
	_.random = function(min, max) {
		if (max == null) {
			max = min;
			min = 0
		}
		return min + (0 | Math.random() * (max - min + 1))
	};
	var entityMap = {
		escape: {
			"&": "&amp;",
			"<": "&lt;",
			">": "&gt;",
			'"': "&quot;",
			"'": "&#x27;",
			"/": "&#x2F;"
		}
	};
	entityMap.unescape = _.invert(entityMap.escape);
	var entityRegexes = {
		escape: new RegExp("[" + _.keys(entityMap.escape).join("") + "]", "g"),
		unescape: new RegExp("(" + _.keys(entityMap.unescape).join("|") + ")", "g")
	};
	_.each(["escape", "unescape"], function(method) {
		_[method] = function(string) {
			if (string == null) return "";
			return ("" + string).replace(entityRegexes[method], function(match) {
				return entityMap[method][match]
			})
		}
	});
	_.result = function(object, property) {
		if (object == null) return null;
		var value = object[property];
		return _.isFunction(value) ? value.call(object) : value
	};
	_.mixin = function(obj) {
		each(_.functions(obj), function(name) {
			var func = _[name] = obj[name];
			_.prototype[name] = function() {
				var args = [this._wrapped];
				push.apply(args, arguments);
				return result.call(this, func.apply(_, args))
			}
		})
	};
	var idCounter = 0;
	_.uniqueId = function(prefix) {
		var id = "" + ++idCounter;
		return prefix ? prefix + id : id
	};
	_.templateSettings = {
		evaluate: /<%([\s\S]+?)%>/g,
		interpolate: /<%=([\s\S]+?)%>/g,
		escape: /<%-([\s\S]+?)%>/g
	};
	var noMatch = /(.)^/;
	var escapes = {
		"'": "'",
		"\\": "\\",
		"\r": "r",
		"\n": "n",
		"	": "t",
		"\u2028": "u2028",
		"\u2029": "u2029"
	};
	var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
	_.template = function(text, data, settings) {
		settings = _.defaults({}, settings, _.templateSettings);
		var matcher = new RegExp([(settings.escape || noMatch).source, (settings.interpolate || noMatch).source, (settings.evaluate || noMatch).source].join("|") + "|$", "g");
		var index = 0;
		var source = "__p+='";
		text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
			source += text.slice(index, offset).replace(escaper, function(match) {
				return "\\" + escapes[match]
			});
			if (escape) {
				source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'"
			}
			if (interpolate) {
				source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'"
			}
			if (evaluate) {
				source += "';\n" + evaluate + "\n__p+='"
			}
			index = offset + match.length;
			return match
		});
		source += "';\n";
		if (!settings.variable) source = "with(obj||{}){\n" + source + "}\n";
		source = "var __t,__p='',__j=Array.prototype.join," + "print=function(){__p+=__j.call(arguments,'');};\n" + source + "return __p;\n";
		try {
			var render = new Function(settings.variable || "obj", "_", source)
		} catch (e) {
			e.source = source;
			throw e
		}
		if (data) return render(data, _);
		var template = function(data) {
			return render.call(this, data, _)
		};
		template.source = "function(" + (settings.variable || "obj") + "){\n" + source + "}";
		return template
	};
	_.chain = function(obj) {
		return _(obj).chain()
	};
	var result = function(obj) {
		return this._chain ? _(obj).chain() : obj
	};
	_.mixin(_);
	each(["pop", "push", "reverse", "shift", "sort", "splice", "unshift"], function(name) {
		var method = ArrayProto[name];
		_.prototype[name] = function() {
			var obj = this._wrapped;
			method.apply(obj, arguments);
			if ((name == "shift" || name == "splice") && obj.length === 0) delete obj[0];
			return result.call(this, obj)
		}
	});
	each(["concat", "join", "slice"], function(name) {
		var method = ArrayProto[name];
		_.prototype[name] = function() {
			return result.call(this, method.apply(this._wrapped, arguments))
		}
	});
	_.extend(_.prototype, {
		chain: function() {
			this._chain = true;
			return this
		},
		value: function() {
			return this._wrapped
		}
	})
}.call(this);
! function(a) {
	String.prototype.trim === a && (String.prototype.trim = function() {
		return this.replace(/^\s+/, "").replace(/\s+$/, "")
	}), Array.prototype.reduce === a && (Array.prototype.reduce = function(b) {
		if (this === void 0 || this === null) throw new TypeError;
		var c = Object(this),
			d = c.length >>> 0,
			e = 0,
			f;
		if (typeof b != "function") throw new TypeError;
		if (d == 0 && arguments.length == 1) throw new TypeError;
		if (arguments.length >= 2) f = arguments[1];
		else
			do {
				if (e in c) {
					f = c[e++];
					break
				}
				if (++e >= d) throw new TypeError
			} while (!0);
		while (e < d) e in c && (f = b.call(a, f, c[e], e, c)), e++;
		return f
	})
}();
var Zepto = function() {
	function A(a) {
		return v.call(a) == "[object Function]"
	}

	function B(a) {
		return a instanceof Object
	}

	function C(b) {
		var c, d;
		if (v.call(b) !== "[object Object]") return !1;
		d = A(b.constructor) && b.constructor.prototype;
		if (!d || !hasOwnProperty.call(d, "isPrototypeOf")) return !1;
		for (c in b);
		return c === a || hasOwnProperty.call(b, c)
	}

	function D(a) {
		return a instanceof Array
	}

	function E(a) {
		return typeof a.length == "number"
	}

	function F(b) {
		return b.filter(function(b) {
			return b !== a && b !== null
		})
	}

	function G(a) {
		return a.length > 0 ? [].concat.apply([], a) : a
	}

	function H(a) {
		return a.replace(/::/g, "/").replace(/([A-Z]+)([A-Z][a-z])/g, "$1_$2").replace(/([a-z\d])([A-Z])/g, "$1_$2").replace(/_/g, "-").toLowerCase()
	}

	function I(a) {
		return a in i ? i[a] : i[a] = new RegExp("(^|\\s)" + a + "(\\s|$)")
	}

	function J(a, b) {
		return typeof b == "number" && !k[H(a)] ? b + "px" : b
	}

	function K(a) {
		var b, c;
		return h[a] || (b = g.createElement(a), g.body.appendChild(b), c = j(b, "").getPropertyValue("display"), b.parentNode.removeChild(b), c == "none" && (c = "block"), h[a] = c), h[a]
	}

	function L(b, d) {
		return d === a ? c(b) : c(b).filter(d)
	}

	function M(a, b, c, d) {
		return A(b) ? b.call(a, c, d) : b
	}

	function N(a, b, d) {
		var e = a % 2 ? b : b.parentNode;
		e ? e.insertBefore(d, a ? a == 1 ? e.firstChild : a == 2 ? b : null : b.nextSibling) : c(d).remove()
	}

	function O(a, b) {
		b(a);
		for (var c in a.childNodes) O(a.childNodes[c], b)
	}
	var a, b, c, d, e = [],
		f = e.slice,
		g = window.document,
		h = {}, i = {}, j = g.defaultView.getComputedStyle,
		k = {
			"column-count": 1,
			columns: 1,
			"font-weight": 1,
			"line-height": 1,
			opacity: 1,
			"z-index": 1,
			zoom: 1
		}, l = /^\s*<(\w+|!)[^>]*>/,
		m = [1, 3, 8, 9, 11],
		n = ["after", "prepend", "before", "append"],
		o = g.createElement("table"),
		p = g.createElement("tr"),
		q = {
			tr: g.createElement("tbody"),
			tbody: o,
			thead: o,
			tfoot: o,
			td: p,
			th: p,
			"*": g.createElement("div")
		}, r = /complete|loaded|interactive/,
		s = /^\.([\w-]+)$/,
		t = /^#([\w-]+)$/,
		u = /^[\w-]+$/,
		v = {}.toString,
		w = {}, x, y, z = g.createElement("div");
	return w.matches = function(a, b) {
		if (!a || a.nodeType !== 1) return !1;
		var c = a.webkitMatchesSelector || a.mozMatchesSelector || a.oMatchesSelector || a.matchesSelector;
		if (c) return c.call(a, b);
		var d, e = a.parentNode,
			f = !e;
		return f && (e = z).appendChild(a), d = ~w.qsa(e, b).indexOf(a), f && z.removeChild(a), d
	}, x = function(a) {
		return a.replace(/-+(.)?/g, function(a, b) {
			return b ? b.toUpperCase() : ""
		})
	}, y = function(a) {
		return a.filter(function(b, c) {
			return a.indexOf(b) == c
		})
	}, w.fragment = function(b, d) {
		d === a && (d = l.test(b) && RegExp.$1), d in q || (d = "*");
		var e = q[d];
		return e.innerHTML = "" + b, c.each(f.call(e.childNodes), function() {
			e.removeChild(this)
		})
	}, w.Z = function(a, b) {
		return a = a || [], a.__proto__ = arguments.callee.prototype, a.selector = b || "", a
	}, w.isZ = function(a) {
		return a instanceof w.Z
	}, w.init = function(b, d) {
		if (!b) return w.Z();
		if (A(b)) return c(g).ready(b);
		if (w.isZ(b)) return b;
		var e;
		if (D(b)) e = F(b);
		else if (C(b)) e = [c.extend({}, b)], b = null;
		else if (m.indexOf(b.nodeType) >= 0 || b === window) e = [b], b = null;
		else if (l.test(b)) e = w.fragment(b.trim(), RegExp.$1), b = null;
		else {
			if (d !== a) return c(d).find(b);
			e = w.qsa(g, b)
		}
		return w.Z(e, b)
	}, c = function(a, b) {
		return w.init(a, b)
	}, c.extend = function(c) {
		return f.call(arguments, 1).forEach(function(d) {
			for (b in d) d[b] !== a && (c[b] = d[b])
		}), c
	}, w.qsa = function(a, b) {
		var c;
		return a === g && t.test(b) ? (c = a.getElementById(RegExp.$1)) ? [c] : e : a.nodeType !== 1 && a.nodeType !== 9 ? e : f.call(s.test(b) ? a.getElementsByClassName(RegExp.$1) : u.test(b) ? a.getElementsByTagName(b) : a.querySelectorAll(b))
	}, c.isFunction = A, c.isObject = B, c.isArray = D, c.isPlainObject = C, c.inArray = function(a, b, c) {
		return e.indexOf.call(b, a, c)
	}, c.trim = function(a) {
		return a.trim()
	}, c.uuid = 0, c.map = function(a, b) {
		var c, d = [],
			e, f;
		if (E(a))
			for (e = 0; e < a.length; e++) c = b(a[e], e), c != null && d.push(c);
		else
			for (f in a) c = b(a[f], f), c != null && d.push(c);
		return G(d)
	}, c.each = function(a, b) {
		var c, d;
		if (E(a)) {
			for (c = 0; c < a.length; c++)
				if (b.call(a[c], c, a[c]) === !1) return a
		} else
			for (d in a)
				if (b.call(a[d], d, a[d]) === !1) return a; return a
	}, c.fn = {
		forEach: e.forEach,
		reduce: e.reduce,
		push: e.push,
		indexOf: e.indexOf,
		concat: e.concat,
		map: function(a) {
			return c.map(this, function(b, c) {
				return a.call(b, c, b)
			})
		},
		slice: function() {
			return c(f.apply(this, arguments))
		},
		ready: function(a) {
			return r.test(g.readyState) ? a(c) : g.addEventListener("DOMContentLoaded", function() {
				a(c)
			}, !1), this
		},
		get: function(b) {
			return b === a ? f.call(this) : this[b]
		},
		toArray: function() {
			return this.get()
		},
		size: function() {
			return this.length
		},
		remove: function() {
			return this.each(function() {
				this.parentNode != null && this.parentNode.removeChild(this)
			})
		},
		each: function(a) {
			return this.forEach(function(b, c) {
				a.call(b, c, b)
			}), this
		},
		filter: function(a) {
			return c([].filter.call(this, function(b) {
				return w.matches(b, a)
			}))
		},
		add: function(a, b) {
			return c(y(this.concat(c(a, b))))
		},
		is: function(a) {
			return this.length > 0 && w.matches(this[0], a)
		},
		not: function(b) {
			var d = [];
			if (A(b) && b.call !== a) this.each(function(a) {
				b.call(this, a) || d.push(this)
			});
			else {
				var e = typeof b == "string" ? this.filter(b) : E(b) && A(b.item) ? f.call(b) : c(b);
				this.forEach(function(a) {
					e.indexOf(a) < 0 && d.push(a)
				})
			}
			return c(d)
		},
		eq: function(a) {
			return a === -1 ? this.slice(a) : this.slice(a, +a + 1)
		},
		first: function() {
			var a = this[0];
			return a && !B(a) ? a : c(a)
		},
		last: function() {
			var a = this[this.length - 1];
			return a && !B(a) ? a : c(a)
		},
		find: function(a) {
			var b;
			return this.length == 1 ? b = w.qsa(this[0], a) : b = this.map(function() {
				return w.qsa(this, a)
			}), c(b)
		},
		closest: function(a, b) {
			var d = this[0];
			while (d && !w.matches(d, a)) d = d !== b && d !== g && d.parentNode;
			return c(d)
		},
		parents: function(a) {
			var b = [],
				d = this;
			while (d.length > 0) d = c.map(d, function(a) {
				if ((a = a.parentNode) && a !== g && b.indexOf(a) < 0) return b.push(a), a
			});
			return L(b, a)
		},
		parent: function(a) {
			return L(y(this.pluck("parentNode")), a)
		},
		children: function(a) {
			return L(this.map(function() {
				return f.call(this.children)
			}), a)
		},
		siblings: function(a) {
			return L(this.map(function(a, b) {
				return f.call(b.parentNode.children).filter(function(a) {
					return a !== b
				})
			}), a)
		},
		empty: function() {
			return this.each(function() {
				this.innerHTML = ""
			})
		},
		pluck: function(a) {
			return this.map(function() {
				return this[a]
			})
		},
		show: function() {
			return this.each(function() {
				this.style.display == "none" && (this.style.display = null), j(this, "").getPropertyValue("display") == "none" && (this.style.display = K(this.nodeName))
			})
		},
		replaceWith: function(a) {
			return this.before(a).remove()
		},
		wrap: function(a) {
			return this.each(function() {
				c(this).wrapAll(c(a)[0].cloneNode(!1))
			})
		},
		wrapAll: function(a) {
			return this[0] && (c(this[0]).before(a = c(a)), a.append(this)), this
		},
		unwrap: function() {
			return this.parent().each(function() {
				c(this).replaceWith(c(this).children())
			}), this
		},
		clone: function() {
			return c(this.map(function() {
				return this.cloneNode(!0)
			}))
		},
		hide: function() {
			return this.css("display", "none")
		},
		toggle: function(b) {
			return (b === a ? this.css("display") == "none" : b) ? this.show() : this.hide()
		},
		prev: function() {
			return c(this.pluck("previousElementSibling"))
		},
		next: function() {
			return c(this.pluck("nextElementSibling"))
		},
		html: function(b) {
			return b === a ? this.length > 0 ? this[0].innerHTML : null : this.each(function(a) {
				var d = this.innerHTML;
				c(this).empty().append(M(this, b, a, d))
			})
		},
		text: function(b) {
			return b === a ? this.length > 0 ? this[0].textContent : null : this.each(function() {
				this.textContent = b
			})
		},
		attr: function(c, d) {
			var e;
			return typeof c == "string" && d === a ? this.length == 0 || this[0].nodeType !== 1 ? a : c == "value" && this[0].nodeName == "INPUT" ? this.val() : !(e = this[0].getAttribute(c)) && c in this[0] ? this[0][c] : e : this.each(function(a) {
				if (this.nodeType !== 1) return;
				if (B(c))
					for (b in c) this.setAttribute(b, c[b]);
				else this.setAttribute(c, M(this, d, a, this.getAttribute(c)))
			})
		},
		removeAttr: function(a) {
			return this.each(function() {
				this.nodeType === 1 && this.removeAttribute(a)
			})
		},
		prop: function(b, c) {
			return c === a ? this[0] ? this[0][b] : a : this.each(function(a) {
				this[b] = M(this, c, a, this[b])
			})
		},
		data: function(b, c) {
			var d = this.attr("data-" + H(b), c);
			return d !== null ? d : a
		},
		val: function(b) {
			return b === a ? this.length > 0 ? this[0].value : a : this.each(function(a) {
				this.value = M(this, b, a, this.value)
			})
		},
		offset: function() {
			if (this.length == 0) return null;
			var a = this[0].getBoundingClientRect();
			return {
				left: a.left + window.pageXOffset,
				top: a.top + window.pageYOffset,
				width: a.width,
				height: a.height
			}
		},
		css: function(c, d) {
			if (d === a && typeof c == "string") return this.length == 0 ? a : this[0].style[x(c)] || j(this[0], "").getPropertyValue(c);
			var e = "";
			for (b in c) typeof c[b] == "string" && c[b] == "" ? this.each(function() {
				this.style.removeProperty(H(b))
			}) : e += H(b) + ":" + J(b, c[b]) + ";";
			return typeof c == "string" && (d == "" ? this.each(function() {
				this.style.removeProperty(H(c))
			}) : e = H(c) + ":" + J(c, d)), this.each(function() {
				this.style.cssText += ";" + e
			})
		},
		index: function(a) {
			return a ? this.indexOf(c(a)[0]) : this.parent().children().indexOf(this[0])
		},
		hasClass: function(a) {
			return this.length < 1 ? !1 : I(a).test(this[0].className)
		},
		addClass: function(a) {
			return this.each(function(b) {
				d = [];
				var e = this.className,
					f = M(this, a, b, e);
				f.split(/\s+/g).forEach(function(a) {
					c(this).hasClass(a) || d.push(a)
				}, this), d.length && (this.className += (e ? " " : "") + d.join(" "))
			})
		},
		removeClass: function(b) {
			return this.each(function(c) {
				if (b === a) return this.className = "";
				d = this.className, M(this, b, c, d).split(/\s+/g).forEach(function(a) {
					d = d.replace(I(a), " ")
				}), this.className = d.trim()
			})
		},
		toggleClass: function(b, d) {
			return this.each(function(e) {
				var f = M(this, b, e, this.className);
				(d === a ? !c(this).hasClass(f) : d) ? c(this).addClass(f) : c(this).removeClass(f)
			})
		}
	}, ["width", "height"].forEach(function(b) {
		c.fn[b] = function(d) {
			var e, f = b.replace(/./, function(a) {
					return a[0].toUpperCase()
				});
			return d === a ? this[0] == window ? window["inner" + f] : this[0] == g ? g.documentElement["offset" + f] : (e = this.offset()) && e[b] : this.each(function(a) {
				var e = c(this);
				e.css(b, M(this, d, a, e[b]()))
			})
		}
	}), n.forEach(function(a, b) {
		c.fn[a] = function() {
			var a = c.map(arguments, function(a) {
				return B(a) ? a : w.fragment(a)
			});
			if (a.length < 1) return this;
			var d = this.length,
				e = d > 1,
				f = b < 2;
			return this.each(function(c, g) {
				for (var h = 0; h < a.length; h++) {
					var i = a[f ? a.length - h - 1 : h];
					O(i, function(a) {
						a.nodeName != null && a.nodeName.toUpperCase() === "SCRIPT" && (!a.type || a.type === "text/javascript") && window.eval.call(window, a.innerHTML)
					}), e && c < d - 1 && (i = i.cloneNode(!0)), N(b, g, i)
				}
			})
		}, c.fn[b % 2 ? a + "To" : "insert" + (b ? "Before" : "After")] = function(b) {
			return c(b)[a](this), this
		}
	}), w.Z.prototype = c.fn, w.camelize = x, w.uniq = y, c.zepto = w, c
}();
window.Zepto = Zepto, "$" in window || (window.$ = Zepto),
function(a) {
	function f(a) {
		return a._zid || (a._zid = d++)
	}

	function g(a, b, d, e) {
		b = h(b);
		if (b.ns) var g = i(b.ns);
		return (c[f(a)] || []).filter(function(a) {
			return a && (!b.e || a.e == b.e) && (!b.ns || g.test(a.ns)) && (!d || f(a.fn) === f(d)) && (!e || a.sel == e)
		})
	}

	function h(a) {
		var b = ("" + a).split(".");
		return {
			e: b[0],
			ns: b.slice(1).sort().join(" ")
		}
	}

	function i(a) {
		return new RegExp("(?:^| )" + a.replace(" ", " .* ?") + "(?: |$)")
	}

	function j(b, c, d) {
		a.isObject(b) ? a.each(b, d) : b.split(/\s/).forEach(function(a) {
			d(a, c)
		})
	}

	function k(b, d, e, g, i, k) {
		k = !! k;
		var l = f(b),
			m = c[l] || (c[l] = []);
		j(d, e, function(c, d) {
			var e = i && i(d, c),
				f = e || d,
				j = function(a) {
					var c = f.apply(b, [a].concat(a.data));
					return c === !1 && a.preventDefault(), c
				}, l = a.extend(h(c), {
					fn: d,
					proxy: j,
					sel: g,
					del: e,
					i: m.length
				});
			m.push(l), b.addEventListener(l.e, j, k)
		})
	}

	function l(a, b, d, e) {
		var h = f(a);
		j(b || "", d, function(b, d) {
			g(a, b, d, e).forEach(function(b) {
				delete c[h][b.i], a.removeEventListener(b.e, b.proxy, !1)
			})
		})
	}

	function p(b) {
		var c = a.extend({
			originalEvent: b
		}, b);
		return a.each(o, function(a, d) {
			c[a] = function() {
				return this[d] = m, b[a].apply(b, arguments)
			}, c[d] = n
		}), c
	}

	function q(a) {
		if (!("defaultPrevented" in a)) {
			a.defaultPrevented = !1;
			var b = a.preventDefault;
			a.preventDefault = function() {
				this.defaultPrevented = !0, b.call(this)
			}
		}
	}
	var b = a.zepto.qsa,
		c = {}, d = 1,
		e = {};
	e.click = e.mousedown = e.mouseup = e.mousemove = "MouseEvents", a.event = {
		add: k,
		remove: l
	}, a.proxy = function(b, c) {
		if (a.isFunction(b)) {
			var d = function() {
				return b.apply(c, arguments)
			};
			return d._zid = f(b), d
		}
		if (typeof c == "string") return a.proxy(b[c], b);
		throw new TypeError("expected function")
	}, a.fn.bind = function(a, b) {
		return this.each(function() {
			k(this, a, b)
		})
	}, a.fn.unbind = function(a, b) {
		return this.each(function() {
			l(this, a, b)
		})
	}, a.fn.one = function(a, b) {
		return this.each(function(c, d) {
			k(this, a, b, null, function(a, b) {
				return function() {
					var c = a.apply(d, arguments);
					return l(d, b, a), c
				}
			})
		})
	};
	var m = function() {
		return !0
	}, n = function() {
			return !1
		}, o = {
			preventDefault: "isDefaultPrevented",
			stopImmediatePropagation: "isImmediatePropagationStopped",
			stopPropagation: "isPropagationStopped"
		};
	a.fn.delegate = function(b, c, d) {
		var e = !1;
		if (c == "blur" || c == "focus") a.iswebkit ? c = c == "blur" ? "focusout" : c == "focus" ? "focusin" : c : e = !0;
		return this.each(function(f, g) {
			k(g, c, d, b, function(c) {
				return function(d) {
					var e, f = a(d.target).closest(b, g).get(0);
					if (f) return e = a.extend(p(d), {
						currentTarget: f,
						liveFired: g
					}), c.apply(f, [e].concat([].slice.call(arguments, 1)))
				}
			}, e)
		})
	}, a.fn.undelegate = function(a, b, c) {
		return this.each(function() {
			l(this, b, c, a)
		})
	}, a.fn.live = function(b, c) {
		return a(document.body).delegate(this.selector, b, c), this
	}, a.fn.die = function(b, c) {
		return a(document.body).undelegate(this.selector, b, c), this
	}, a.fn.on = function(b, c, d) {
		return c == undefined || a.isFunction(c) ? this.bind(b, c) : this.delegate(c, b, d)
	}, a.fn.off = function(b, c, d) {
		return c == undefined || a.isFunction(c) ? this.unbind(b, c) : this.undelegate(c, b, d)
	}, a.fn.trigger = function(b, c) {
		return typeof b == "string" && (b = a.Event(b)), q(b), b.data = c, this.each(function() {
			"dispatchEvent" in this && this.dispatchEvent(b)
		})
	}, a.fn.triggerHandler = function(b, c) {
		var d, e;
		return this.each(function(f, h) {
			d = p(typeof b == "string" ? a.Event(b) : b), d.data = c, d.target = h, a.each(g(h, b.type || b), function(a, b) {
				e = b.proxy(d);
				if (d.isImmediatePropagationStopped()) return !1
			})
		}), e
	}, "focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout change select keydown keypress keyup error".split(" ").forEach(function(b) {
		a.fn[b] = function(a) {
			return this.bind(b, a)
		}
	}), ["focus", "blur"].forEach(function(b) {
		a.fn[b] = function(a) {
			if (a) this.bind(b, a);
			else if (this.length) try {
				this.get(0)[b]()
			} catch (c) {}
			return this
		}
	}), a.Event = function(a, b) {
		var c = document.createEvent(e[a] || "Events"),
			d = !0;
		if (b)
			for (var f in b) f == "bubbles" ? d = !! b[f] : c[f] = b[f];
		return c.initEvent(a, d, !0, null, null, null, null, null, null, null, null, null, null, null, null), c
	}
}(Zepto),
function(a) {
	function b(a) {
		var b = this.os = {}, c = this.browser = {}, d = a.match(/WebKit\/([\d.]+)/),
			e = a.match(/(Android)\s+([\d.]+)/),
			f = a.match(/(iPad).*OS\s([\d_]+)/),
			g = !f && a.match(/(iPhone\sOS)\s([\d_]+)/),
			h = a.match(/(webOS|hpwOS)[\s\/]([\d.]+)/),
			i = h && a.match(/TouchPad/),
			j = a.match(/Kindle\/([\d.]+)/),
			k = a.match(/Silk\/([\d._]+)/),
			l = a.match(/(BlackBerry).*Version\/([\d.]+)/);
		if (c.webkit = !! d) c.version = d[1];
		e && (b.android = !0, b.version = e[2]), g && (b.ios = b.iphone = !0, b.version = g[2].replace(/_/g, ".")), f && (b.ios = b.ipad = !0, b.version = f[2].replace(/_/g, ".")), h && (b.webos = !0, b.version = h[2]), i && (b.touchpad = !0), l && (b.blackberry = !0, b.version = l[2]), j && (b.kindle = !0, b.version = j[1]), k && (c.silk = !0, c.version = k[1]), !k && b.android && a.match(/Kindle Fire/) && (c.silk = !0)
	}
	b.call(a, navigator.userAgent), a.__detect = b
}(Zepto),
function(a, b) {
	function l(a) {
		return a.toLowerCase()
	}

	function m(a) {
		return d ? d + a : l(a)
	}
	var c = "",
		d, e, f, g = {
			Webkit: "webkit",
			Moz: "",
			O: "o",
			ms: "MS"
		}, h = window.document,
		i = h.createElement("div"),
		j = /^((translate|rotate|scale)(X|Y|Z|3d)?|matrix(3d)?|perspective|skew(X|Y)?)$/i,
		k = {};
	a.each(g, function(a, e) {
		if (i.style[a + "TransitionProperty"] !== b) return c = "-" + l(a) + "-", d = e, !1
	}), k[c + "transition-property"] = k[c + "transition-duration"] = k[c + "transition-timing-function"] = k[c + "animation-name"] = k[c + "animation-duration"] = "", a.fx = {
		off: d === b && i.style.transitionProperty === b,
		cssPrefix: c,
		transitionEnd: m("TransitionEnd"),
		animationEnd: m("AnimationEnd")
	}, a.fn.animate = function(b, c, d, e) {
		return a.isObject(c) && (d = c.easing, e = c.complete, c = c.duration), c && (c /= 1e3), this.anim(b, c, d, e)
	}, a.fn.anim = function(d, e, f, g) {
		var h, i = {}, l, m = this,
			n, o = a.fx.transitionEnd;
		e === b && (e = .4), a.fx.off && (e = 0);
		if (typeof d == "string") i[c + "animation-name"] = d, i[c + "animation-duration"] = e + "s", o = a.fx.animationEnd;
		else {
			for (l in d) j.test(l) ? (h || (h = []), h.push(l + "(" + d[l] + ")")) : i[l] = d[l];
			h && (i[c + "transform"] = h.join(" ")), !a.fx.off && typeof d == "object" && (i[c + "transition-property"] = Object.keys(d).join(", "), i[c + "transition-duration"] = e + "s", i[c + "transition-timing-function"] = f || "linear")
		}
		return n = function(b) {
			if (typeof b != "undefined") {
				if (b.target !== b.currentTarget) return;
				a(b.target).unbind(o, arguments.callee)
			}
			a(this).css(k), g && g.call(this)
		}, e > 0 && this.bind(o, n), setTimeout(function() {
			m.css(i), e <= 0 && setTimeout(function() {
				m.each(function() {
					n.call(this)
				})
			}, 0)
		}, 0), this
	}, i = null
}(Zepto),
function($) {
	function triggerAndReturn(a, b, c) {
		var d = $.Event(b);
		return $(a).trigger(d, c), !d.defaultPrevented
	}

	function triggerGlobal(a, b, c, d) {
		if (a.global) return triggerAndReturn(b || document, c, d)
	}

	function ajaxStart(a) {
		a.global && $.active++ === 0 && triggerGlobal(a, null, "ajaxStart")
	}

	function ajaxStop(a) {
		a.global && !--$.active && triggerGlobal(a, null, "ajaxStop")
	}

	function ajaxBeforeSend(a, b) {
		var c = b.context;
		if (b.beforeSend.call(c, a, b) === !1 || triggerGlobal(b, c, "ajaxBeforeSend", [a, b]) === !1) return !1;
		triggerGlobal(b, c, "ajaxSend", [a, b])
	}

	function ajaxSuccess(a, b, c) {
		var d = c.context,
			e = "success";
		c.success.call(d, a, e, b), triggerGlobal(c, d, "ajaxSuccess", [b, c, a]), ajaxComplete(e, b, c)
	}

	function ajaxError(a, b, c, d) {
		var e = d.context;
		d.error.call(e, c, b, a), triggerGlobal(d, e, "ajaxError", [c, d, a]), ajaxComplete(b, c, d)
	}

	function ajaxComplete(a, b, c) {
		var d = c.context;
		c.complete.call(d, b, a), triggerGlobal(c, d, "ajaxComplete", [b, c]), ajaxStop(c)
	}

	function empty() {}

	function mimeToDataType(a) {
		return a && (a == htmlType ? "html" : a == jsonType ? "json" : scriptTypeRE.test(a) ? "script" : xmlTypeRE.test(a) && "xml") || "text"
	}

	function appendQuery(a, b) {
		return (a + "&" + b).replace(/[&?]{1,2}/, "?")
	}

	function serializeData(a) {
		isObject(a.data) && (a.data = $.param(a.data)), a.data && (!a.type || a.type.toUpperCase() == "GET") && (a.url = appendQuery(a.url, a.data))
	}

	function serialize(a, b, c, d) {
		var e = $.isArray(b);
		$.each(b, function(b, f) {
			d && (b = c ? d : d + "[" + (e ? "" : b) + "]"), !d && e ? a.add(f.name, f.value) : (c ? $.isArray(f) : isObject(f)) ? serialize(a, f, c, b) : a.add(b, f)
		})
	}
	var jsonpID = 0,
		isObject = $.isObject,
		document = window.document,
		key, name, rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
		scriptTypeRE = /^(?:text|application)\/javascript/i,
		xmlTypeRE = /^(?:text|application)\/xml/i,
		jsonType = "application/json",
		htmlType = "text/html",
		blankRE = /^\s*$/;
	$.active = 0, $.ajaxJSONP = function(a) {
		var b = "jsonp" + ++jsonpID,
			c = document.createElement("script"),
			d = function() {
				$(c).remove(), b in window && (window[b] = empty), ajaxComplete("abort", e, a)
			}, e = {
				abort: d
			}, f;
		return a.error && (c.onerror = function() {
			e.abort(), a.error()
		}), window[b] = function(d) {
			clearTimeout(f), $(c).remove(), delete window[b], ajaxSuccess(d, e, a)
		}, serializeData(a), c.src = a.url.replace(/=\?/, "=" + b), $("head").append(c), a.timeout > 0 && (f = setTimeout(function() {
			e.abort(), ajaxComplete("timeout", e, a)
		}, a.timeout)), e
	}, $.ajaxSettings = {
		type: "GET",
		beforeSend: empty,
		success: empty,
		error: empty,
		complete: empty,
		context: null,
		global: !0,
		xhr: function() {
			return new window.XMLHttpRequest
		},
		accepts: {
			script: "text/javascript, application/javascript",
			json: jsonType,
			xml: "application/xml, text/xml",
			html: htmlType,
			text: "text/plain"
		},
		crossDomain: !1,
		timeout: 0
	}, $.ajax = function(options) {
		var settings = $.extend({}, options || {});
		for (key in $.ajaxSettings) settings[key] === undefined && (settings[key] = $.ajaxSettings[key]);
		ajaxStart(settings), settings.crossDomain || (settings.crossDomain = /^([\w-]+:)?\/\/([^\/]+)/.test(settings.url) && RegExp.$2 != window.location.host);
		var dataType = settings.dataType,
			hasPlaceholder = /=\?/.test(settings.url);
		if (dataType == "jsonp" || hasPlaceholder) return hasPlaceholder || (settings.url = appendQuery(settings.url, "callback=?")), $.ajaxJSONP(settings);
		settings.url || (settings.url = window.location.toString()), serializeData(settings);
		var mime = settings.accepts[dataType],
			baseHeaders = {}, protocol = /^([\w-]+:)\/\//.test(settings.url) ? RegExp.$1 : window.location.protocol,
			xhr = $.ajaxSettings.xhr(),
			abortTimeout;
		settings.crossDomain || (baseHeaders["X-Requested-With"] = "XMLHttpRequest"), mime && (baseHeaders.Accept = mime, mime.indexOf(",") > -1 && (mime = mime.split(",", 2)[0]), xhr.overrideMimeType && xhr.overrideMimeType(mime));
		if (settings.contentType || settings.data && settings.type.toUpperCase() != "GET") baseHeaders["Content-Type"] = settings.contentType || "application/x-www-form-urlencoded";
		settings.headers = $.extend(baseHeaders, settings.headers || {}), xhr.onreadystatechange = function() {
			if (xhr.readyState == 4) {
				clearTimeout(abortTimeout);
				var result, error = !1;
				if (xhr.status >= 200 && xhr.status < 300 || xhr.status == 304 || xhr.status == 0 && protocol == "file:") {
					dataType = dataType || mimeToDataType(xhr.getResponseHeader("content-type")), result = xhr.responseText;
					try {
						dataType == "script" ? (1, eval)(result) : dataType == "xml" ? result = xhr.responseXML : dataType == "json" && (result = blankRE.test(result) ? null : JSON.parse(result))
					} catch (e) {
						error = e
					}
					error ? ajaxError(error, "parsererror", xhr, settings) : ajaxSuccess(result, xhr, settings)
				} else ajaxError(null, "error", xhr, settings)
			}
		};
		var async = "async" in settings ? settings.async : !0;
		xhr.open(settings.type, settings.url, async);
		for (name in settings.headers) xhr.setRequestHeader(name, settings.headers[name]);
		return ajaxBeforeSend(xhr, settings) === !1 ? (xhr.abort(), !1) : (settings.timeout > 0 && (abortTimeout = setTimeout(function() {
			xhr.onreadystatechange = empty, xhr.abort(), ajaxError(null, "timeout", xhr, settings)
		}, settings.timeout)), xhr.send(settings.data ? settings.data : null), xhr)
	}, $.get = function(a, b) {
		return $.ajax({
			url: a,
			success: b
		})
	}, $.post = function(a, b, c, d) {
		return $.isFunction(b) && (d = d || c, c = b, b = null), $.ajax({
			type: "POST",
			url: a,
			data: b,
			success: c,
			dataType: d
		})
	}, $.getJSON = function(a, b) {
		return $.ajax({
			url: a,
			success: b,
			dataType: "json"
		})
	}, $.fn.load = function(a, b) {
		if (!this.length) return this;
		var c = this,
			d = a.split(/\s/),
			e;
		return d.length > 1 && (a = d[0], e = d[1]), $.get(a, function(a) {
			c.html(e ? $(document.createElement("div")).html(a.replace(rscript, "")).find(e).html() : a), b && b.call(c)
		}), this
	};
	var escape = encodeURIComponent;
	$.param = function(a, b) {
		var c = [];
		return c.add = function(a, b) {
			this.push(escape(a) + "=" + escape(b))
		}, serialize(c, a, b), c.join("&").replace("%20", "+")
	}
}(Zepto),
function(a) {
	a.fn.serializeArray = function() {
		var b = [],
			c;
		return a(Array.prototype.slice.call(this.get(0).elements)).each(function() {
			c = a(this);
			var d = c.attr("type");
			this.nodeName.toLowerCase() != "fieldset" && !this.disabled && d != "submit" && d != "reset" && d != "button" && (d != "radio" && d != "checkbox" || this.checked) && b.push({
				name: c.attr("name"),
				value: c.val()
			})
		}), b
	}, a.fn.serialize = function() {
		var a = [];
		return this.serializeArray().forEach(function(b) {
			a.push(encodeURIComponent(b.name) + "=" + encodeURIComponent(b.value))
		}), a.join("&")
	}, a.fn.submit = function(b) {
		if (b) this.bind("submit", b);
		else if (this.length) {
			var c = a.Event("submit");
			this.eq(0).trigger(c), c.defaultPrevented || this.get(0).submit()
		}
		return this
	}
}(Zepto),
function(a) {
	function d(a) {
		return "tagName" in a ? a : a.parentNode
	}

	function e(a, b, c, d) {
		var e = Math.abs(a - b),
			f = Math.abs(c - d);
		return e >= f ? a - b > 0 ? "Left" : "Right" : c - d > 0 ? "Up" : "Down"
	}

	function h() {
		g = null, b.last && (b.el.trigger("longTap"), b = {})
	}

	function i() {
		g && clearTimeout(g), g = null
	}
	var b = {}, c, f = 750,
		g;
	a(document).ready(function() {
		var j, k;
		a(document.body).bind("touchstart", function(e) {
			j = Date.now(), k = j - (b.last || j), b.el = a(d(e.touches[0].target)), c && clearTimeout(c), b.x1 = e.touches[0].pageX, b.y1 = e.touches[0].pageY, k > 0 && k <= 250 && (b.isDoubleTap = !0), b.last = j, g = setTimeout(h, f)
		}).bind("touchmove", function(a) {
			i(), b.x2 = a.touches[0].pageX, b.y2 = a.touches[0].pageY
		}).bind("touchend", function(a) {
			i(), b.isDoubleTap ? (b.el.trigger("doubleTap"), b = {}) : b.x2 && Math.abs(b.x1 - b.x2) > 30 || b.y2 && Math.abs(b.y1 - b.y2) > 30 ? (b.el.trigger("swipe") && b.el.trigger("swipe" + e(b.x1, b.x2, b.y1, b.y2)), b = {}) : "last" in b && (b.el.trigger("tap"), c = setTimeout(function() {
				c = null, b.el.trigger("singleTap"), b = {}
			}, 250))
		}).bind("touchcancel", function() {
			c && clearTimeout(c), g && clearTimeout(g), g = c = null, b = {}
		})
	}), ["swipe", "swipeLeft", "swipeRight", "swipeUp", "swipeDown", "doubleTap", "tap", "singleTap", "longTap"].forEach(function(b) {
		a.fn[b] = function(a) {
			return this.bind(b, a)
		}
	})
}(Zepto);
! function() {
	var root = this;
	var previousBackbone = root.Backbone;
	var array = [];
	var push = array.push;
	var slice = array.slice;
	var splice = array.splice;
	var Backbone;
	if (typeof exports !== "undefined") {
		Backbone = exports
	} else {
		Backbone = root.Backbone = {}
	}
	Backbone.VERSION = "1.0.0";
	var _ = root._;
	if (!_ && typeof require !== "undefined") _ = require("underscore");
	Backbone.$ = root.jQuery || root.Zepto || root.ender || root.$;
	Backbone.noConflict = function() {
		root.Backbone = previousBackbone;
		return this
	};
	Backbone.emulateHTTP = false;
	Backbone.emulateJSON = false;
	var Events = Backbone.Events = {
		on: function(name, callback, context) {
			if (!eventsApi(this, "on", name, [callback, context]) || !callback) return this;
			this._events || (this._events = {});
			var events = this._events[name] || (this._events[name] = []);
			events.push({
				callback: callback,
				context: context,
				ctx: context || this
			});
			return this
		},
		once: function(name, callback, context) {
			if (!eventsApi(this, "once", name, [callback, context]) || !callback) return this;
			var self = this;
			var once = _.once(function() {
				self.off(name, once);
				callback.apply(this, arguments)
			});
			once._callback = callback;
			return this.on(name, once, context)
		},
		off: function(name, callback, context) {
			var retain, ev, events, names, i, l, j, k;
			if (!this._events || !eventsApi(this, "off", name, [callback, context])) return this;
			if (!name && !callback && !context) {
				this._events = {};
				return this
			}
			names = name ? [name] : _.keys(this._events);
			for (i = 0, l = names.length; i < l; i++) {
				name = names[i];
				if (events = this._events[name]) {
					this._events[name] = retain = [];
					if (callback || context) {
						for (j = 0, k = events.length; j < k; j++) {
							ev = events[j];
							if (callback && callback !== ev.callback && callback !== ev.callback._callback || context && context !== ev.context) {
								retain.push(ev)
							}
						}
					}
					if (!retain.length) delete this._events[name]
				}
			}
			return this
		},
		trigger: function(name) {
			if (!this._events) return this;
			var args = slice.call(arguments, 1);
			if (!eventsApi(this, "trigger", name, args)) return this;
			var events = this._events[name];
			var allEvents = this._events.all;
			if (events) triggerEvents(events, args);
			if (allEvents) triggerEvents(allEvents, arguments);
			return this
		},
		stopListening: function(obj, name, callback) {
			var listeners = this._listeners;
			if (!listeners) return this;
			var deleteListener = !name && !callback;
			if (typeof name === "object") callback = this;
			if (obj)(listeners = {})[obj._listenerId] = obj;
			for (var id in listeners) {
				listeners[id].off(name, callback, this);
				if (deleteListener) delete this._listeners[id]
			}
			return this
		}
	};
	var eventSplitter = /\s+/;
	var eventsApi = function(obj, action, name, rest) {
		if (!name) return true;
		if (typeof name === "object") {
			for (var key in name) {
				obj[action].apply(obj, [key, name[key]].concat(rest))
			}
			return false
		}
		if (eventSplitter.test(name)) {
			var names = name.split(eventSplitter);
			for (var i = 0, l = names.length; i < l; i++) {
				obj[action].apply(obj, [names[i]].concat(rest))
			}
			return false
		}
		return true
	};
	var triggerEvents = function(events, args) {
		var ev, i = -1,
			l = events.length,
			a1 = args[0],
			a2 = args[1],
			a3 = args[2];
		switch (args.length) {
			case 0:
				while (++i < l)(ev = events[i]).callback.call(ev.ctx);
				return;
			case 1:
				while (++i < l)(ev = events[i]).callback.call(ev.ctx, a1);
				return;
			case 2:
				while (++i < l)(ev = events[i]).callback.call(ev.ctx, a1, a2);
				return;
			case 3:
				while (++i < l)(ev = events[i]).callback.call(ev.ctx, a1, a2, a3);
				return;
			default:
				while (++i < l)(ev = events[i]).callback.apply(ev.ctx, args)
		}
	};
	var listenMethods = {
		listenTo: "on",
		listenToOnce: "once"
	};
	_.each(listenMethods, function(implementation, method) {
		Events[method] = function(obj, name, callback) {
			var listeners = this._listeners || (this._listeners = {});
			var id = obj._listenerId || (obj._listenerId = _.uniqueId("l"));
			listeners[id] = obj;
			if (typeof name === "object") callback = this;
			obj[implementation](name, callback, this);
			return this
		}
	});
	Events.bind = Events.on;
	Events.unbind = Events.off;
	_.extend(Backbone, Events);
	var Model = Backbone.Model = function(attributes, options) {
		var defaults;
		var attrs = attributes || {};
		options || (options = {});
		this.cid = _.uniqueId("c");
		this.attributes = {};
		_.extend(this, _.pick(options, modelOptions));
		if (options.parse) attrs = this.parse(attrs, options) || {};
		if (defaults = _.result(this, "defaults")) {
			attrs = _.defaults({}, attrs, defaults)
		}
		this.set(attrs, options);
		this.changed = {};
		this.initialize.apply(this, arguments)
	};
	var modelOptions = ["url", "urlRoot", "collection"];
	_.extend(Model.prototype, Events, {
		changed: null,
		validationError: null,
		idAttribute: "id",
		initialize: function() {},
		toJSON: function(options) {
			return _.clone(this.attributes)
		},
		sync: function() {
			return Backbone.sync.apply(this, arguments)
		},
		get: function(attr) {
			return this.attributes[attr]
		},
		escape: function(attr) {
			return _.escape(this.get(attr))
		},
		has: function(attr) {
			return this.get(attr) != null
		},
		set: function(key, val, options) {
			var attr, attrs, unset, changes, silent, changing, prev, current;
			if (key == null) return this;
			if (typeof key === "object") {
				attrs = key;
				options = val
			} else {
				(attrs = {})[key] = val
			}
			options || (options = {});
			if (!this._validate(attrs, options)) return false;
			unset = options.unset;
			silent = options.silent;
			changes = [];
			changing = this._changing;
			this._changing = true;
			if (!changing) {
				this._previousAttributes = _.clone(this.attributes);
				this.changed = {}
			}
			current = this.attributes, prev = this._previousAttributes;
			if (this.idAttribute in attrs) this.id = attrs[this.idAttribute];
			for (attr in attrs) {
				val = attrs[attr];
				if (!_.isEqual(current[attr], val)) changes.push(attr);
				if (!_.isEqual(prev[attr], val)) {
					this.changed[attr] = val
				} else {
					delete this.changed[attr]
				}
				unset ? delete current[attr] : current[attr] = val
			}
			if (!silent) {
				if (changes.length) this._pending = true;
				for (var i = 0, l = changes.length; i < l; i++) {
					this.trigger("change:" + changes[i], this, current[changes[i]], options)
				}
			}
			if (changing) return this;
			if (!silent) {
				while (this._pending) {
					this._pending = false;
					this.trigger("change", this, options)
				}
			}
			this._pending = false;
			this._changing = false;
			return this
		},
		unset: function(attr, options) {
			return this.set(attr, void 0, _.extend({}, options, {
				unset: true
			}))
		},
		clear: function(options) {
			var attrs = {};
			for (var key in this.attributes) attrs[key] = void 0;
			return this.set(attrs, _.extend({}, options, {
				unset: true
			}))
		},
		hasChanged: function(attr) {
			if (attr == null) return !_.isEmpty(this.changed);
			return _.has(this.changed, attr)
		},
		changedAttributes: function(diff) {
			if (!diff) return this.hasChanged() ? _.clone(this.changed) : false;
			var val, changed = false;
			var old = this._changing ? this._previousAttributes : this.attributes;
			for (var attr in diff) {
				if (_.isEqual(old[attr], val = diff[attr])) continue;
				(changed || (changed = {}))[attr] = val
			}
			return changed
		},
		previous: function(attr) {
			if (attr == null || !this._previousAttributes) return null;
			return this._previousAttributes[attr]
		},
		previousAttributes: function() {
			return _.clone(this._previousAttributes)
		},
		fetch: function(options) {
			options = options ? _.clone(options) : {};
			if (options.parse === void 0) options.parse = true;
			var model = this;
			var success = options.success;
			options.success = function(resp) {
				if (!model.set(model.parse(resp, options), options)) return false;
				if (success) success(model, resp, options);
				model.trigger("sync", model, resp, options)
			};
			wrapError(this, options);
			return this.sync("read", this, options)
		},
		save: function(key, val, options) {
			var attrs, method, xhr, attributes = this.attributes;
			if (key == null || typeof key === "object") {
				attrs = key;
				options = val
			} else {
				(attrs = {})[key] = val
			} if (attrs && (!options || !options.wait) && !this.set(attrs, options)) return false;
			options = _.extend({
				validate: true
			}, options);
			if (!this._validate(attrs, options)) return false;
			if (attrs && options.wait) {
				this.attributes = _.extend({}, attributes, attrs)
			}
			if (options.parse === void 0) options.parse = true;
			var model = this;
			var success = options.success;
			options.success = function(resp) {
				model.attributes = attributes;
				var serverAttrs = model.parse(resp, options);
				if (options.wait) serverAttrs = _.extend(attrs || {}, serverAttrs);
				if (_.isObject(serverAttrs) && !model.set(serverAttrs, options)) {
					return false
				}
				if (success) success(model, resp, options);
				model.trigger("sync", model, resp, options)
			};
			wrapError(this, options);
			method = this.isNew() ? "create" : options.patch ? "patch" : "update";
			if (method === "patch") options.attrs = attrs;
			xhr = this.sync(method, this, options);
			if (attrs && options.wait) this.attributes = attributes;
			return xhr
		},
		destroy: function(options) {
			options = options ? _.clone(options) : {};
			var model = this;
			var success = options.success;
			var destroy = function() {
				model.trigger("destroy", model, model.collection, options)
			};
			options.success = function(resp) {
				if (options.wait || model.isNew()) destroy();
				if (success) success(model, resp, options);
				if (!model.isNew()) model.trigger("sync", model, resp, options)
			};
			if (this.isNew()) {
				options.success();
				return false
			}
			wrapError(this, options);
			var xhr = this.sync("delete", this, options);
			if (!options.wait) destroy();
			return xhr
		},
		url: function() {
			var base = _.result(this, "urlRoot") || _.result(this.collection, "url") || urlError();
			if (this.isNew()) return base;
			return base + (base.charAt(base.length - 1) === "/" ? "" : "/") + encodeURIComponent(this.id)
		},
		parse: function(resp, options) {
			return resp
		},
		clone: function() {
			return new this.constructor(this.attributes)
		},
		isNew: function() {
			return this.id == null
		},
		isValid: function(options) {
			return this._validate({}, _.extend(options || {}, {
				validate: true
			}))
		},
		_validate: function(attrs, options) {
			if (!options.validate || !this.validate) return true;
			attrs = _.extend({}, this.attributes, attrs);
			var error = this.validationError = this.validate(attrs, options) || null;
			if (!error) return true;
			this.trigger("invalid", this, error, _.extend(options || {}, {
				validationError: error
			}));
			return false
		}
	});
	var modelMethods = ["keys", "values", "pairs", "invert", "pick", "omit"];
	_.each(modelMethods, function(method) {
		Model.prototype[method] = function() {
			var args = slice.call(arguments);
			args.unshift(this.attributes);
			return _[method].apply(_, args)
		}
	});
	var Collection = Backbone.Collection = function(models, options) {
		options || (options = {});
		if (options.url) this.url = options.url;
		if (options.model) this.model = options.model;
		if (options.comparator !== void 0) this.comparator = options.comparator;
		this._reset();
		this.initialize.apply(this, arguments);
		if (models) this.reset(models, _.extend({
			silent: true
		}, options))
	};
	var setOptions = {
		add: true,
		remove: true,
		merge: true
	};
	var addOptions = {
		add: true,
		merge: false,
		remove: false
	};
	_.extend(Collection.prototype, Events, {
		model: Model,
		initialize: function() {},
		toJSON: function(options) {
			return this.map(function(model) {
				return model.toJSON(options)
			})
		},
		sync: function() {
			return Backbone.sync.apply(this, arguments)
		},
		add: function(models, options) {
			return this.set(models, _.defaults(options || {}, addOptions))
		},
		remove: function(models, options) {
			models = _.isArray(models) ? models.slice() : [models];
			options || (options = {});
			var i, l, index, model;
			for (i = 0, l = models.length; i < l; i++) {
				model = this.get(models[i]);
				if (!model) continue;
				delete this._byId[model.id];
				delete this._byId[model.cid];
				index = this.indexOf(model);
				this.models.splice(index, 1);
				this.length--;
				if (!options.silent) {
					options.index = index;
					model.trigger("remove", model, this, options)
				}
				this._removeReference(model)
			}
			return this
		},
		set: function(models, options) {
			options = _.defaults(options || {}, setOptions);
			if (options.parse) models = this.parse(models, options);
			if (!_.isArray(models)) models = models ? [models] : [];
			var i, l, model, attrs, existing, sort;
			var at = options.at;
			var sortable = this.comparator && at == null && options.sort !== false;
			var sortAttr = _.isString(this.comparator) ? this.comparator : null;
			var toAdd = [],
				toRemove = [],
				modelMap = {};
			for (i = 0, l = models.length; i < l; i++) {
				if (!(model = this._prepareModel(models[i], options))) continue;
				if (existing = this.get(model)) {
					if (options.remove) modelMap[existing.cid] = true;
					if (options.merge) {
						existing.set(model.attributes, options);
						if (sortable && !sort && existing.hasChanged(sortAttr)) sort = true
					}
				} else if (options.add) {
					toAdd.push(model);
					model.on("all", this._onModelEvent, this);
					this._byId[model.cid] = model;
					if (model.id != null) this._byId[model.id] = model
				}
			}
			if (options.remove) {
				for (i = 0, l = this.length; i < l; ++i) {
					if (!modelMap[(model = this.models[i]).cid]) toRemove.push(model)
				}
				if (toRemove.length) this.remove(toRemove, options)
			}
			if (toAdd.length) {
				if (sortable) sort = true;
				this.length += toAdd.length;
				if (at != null) {
					splice.apply(this.models, [at, 0].concat(toAdd))
				} else {
					push.apply(this.models, toAdd)
				}
			}
			if (sort) this.sort({
				silent: true
			});
			if (options.silent) return this;
			for (i = 0, l = toAdd.length; i < l; i++) {
				(model = toAdd[i]).trigger("add", model, this, options)
			}
			if (sort) this.trigger("sort", this, options);
			return this
		},
		reset: function(models, options) {
			options || (options = {});
			for (var i = 0, l = this.models.length; i < l; i++) {
				this._removeReference(this.models[i])
			}
			options.previousModels = this.models;
			this._reset();
			this.add(models, _.extend({
				silent: true
			}, options));
			if (!options.silent) this.trigger("reset", this, options);
			return this
		},
		push: function(model, options) {
			model = this._prepareModel(model, options);
			this.add(model, _.extend({
				at: this.length
			}, options));
			return model
		},
		pop: function(options) {
			var model = this.at(this.length - 1);
			this.remove(model, options);
			return model
		},
		unshift: function(model, options) {
			model = this._prepareModel(model, options);
			this.add(model, _.extend({
				at: 0
			}, options));
			return model
		},
		shift: function(options) {
			var model = this.at(0);
			this.remove(model, options);
			return model
		},
		slice: function(begin, end) {
			return this.models.slice(begin, end)
		},
		get: function(obj) {
			if (obj == null) return void 0;
			return this._byId[obj.id != null ? obj.id : obj.cid || obj]
		},
		at: function(index) {
			return this.models[index]
		},
		where: function(attrs, first) {
			if (_.isEmpty(attrs)) return first ? void 0 : [];
			return this[first ? "find" : "filter"](function(model) {
				for (var key in attrs) {
					if (attrs[key] !== model.get(key)) return false
				}
				return true
			})
		},
		findWhere: function(attrs) {
			return this.where(attrs, true)
		},
		sort: function(options) {
			if (!this.comparator) throw new Error("Cannot sort a set without a comparator");
			options || (options = {});
			if (_.isString(this.comparator) || this.comparator.length === 1) {
				this.models = this.sortBy(this.comparator, this)
			} else {
				this.models.sort(_.bind(this.comparator, this))
			} if (!options.silent) this.trigger("sort", this, options);
			return this
		},
		sortedIndex: function(model, value, context) {
			value || (value = this.comparator);
			var iterator = _.isFunction(value) ? value : function(model) {
					return model.get(value)
				};
			return _.sortedIndex(this.models, model, iterator, context)
		},
		pluck: function(attr) {
			return _.invoke(this.models, "get", attr)
		},
		fetch: function(options) {
			options = options ? _.clone(options) : {};
			if (options.parse === void 0) options.parse = true;
			var success = options.success;
			var collection = this;
			options.success = function(resp) {
				var method = options.reset ? "reset" : "set";
				collection[method](resp, options);
				if (success) success(collection, resp, options);
				collection.trigger("sync", collection, resp, options)
			};
			wrapError(this, options);
			return this.sync("read", this, options)
		},
		create: function(model, options) {
			options = options ? _.clone(options) : {};
			if (!(model = this._prepareModel(model, options))) return false;
			if (!options.wait) this.add(model, options);
			var collection = this;
			var success = options.success;
			options.success = function(resp) {
				if (options.wait) collection.add(model, options);
				if (success) success(model, resp, options)
			};
			model.save(null, options);
			return model
		},
		parse: function(resp, options) {
			return resp
		},
		clone: function() {
			return new this.constructor(this.models)
		},
		_reset: function() {
			this.length = 0;
			this.models = [];
			this._byId = {}
		},
		_prepareModel: function(attrs, options) {
			if (attrs instanceof Model) {
				if (!attrs.collection) attrs.collection = this;
				return attrs
			}
			options || (options = {});
			options.collection = this;
			var model = new this.model(attrs, options);
			if (!model._validate(attrs, options)) {
				this.trigger("invalid", this, attrs, options);
				return false
			}
			return model
		},
		_removeReference: function(model) {
			if (this === model.collection) delete model.collection;
			model.off("all", this._onModelEvent, this)
		},
		_onModelEvent: function(event, model, collection, options) {
			if ((event === "add" || event === "remove") && collection !== this) return;
			if (event === "destroy") this.remove(model, options);
			if (model && event === "change:" + model.idAttribute) {
				delete this._byId[model.previous(model.idAttribute)];
				if (model.id != null) this._byId[model.id] = model
			}
			this.trigger.apply(this, arguments)
		}
	});
	var methods = ["forEach", "each", "map", "collect", "reduce", "foldl", "inject", "reduceRight", "foldr", "find", "detect", "filter", "select", "reject", "every", "all", "some", "any", "include", "contains", "invoke", "max", "min", "toArray", "size", "first", "head", "take", "initial", "rest", "tail", "drop", "last", "without", "indexOf", "shuffle", "lastIndexOf", "isEmpty", "chain"];
	_.each(methods, function(method) {
		Collection.prototype[method] = function() {
			var args = slice.call(arguments);
			args.unshift(this.models);
			return _[method].apply(_, args)
		}
	});
	var attributeMethods = ["groupBy", "countBy", "sortBy"];
	_.each(attributeMethods, function(method) {
		Collection.prototype[method] = function(value, context) {
			var iterator = _.isFunction(value) ? value : function(model) {
					return model.get(value)
				};
			return _[method](this.models, iterator, context)
		}
	});
	var View = Backbone.View = function(options) {
		this.cid = _.uniqueId("view");
		this._configure(options || {});
		this._ensureElement();
		this.initialize.apply(this, arguments);
		this.delegateEvents()
	};
	var delegateEventSplitter = /^(\S+)\s*(.*)$/;
	var viewOptions = ["model", "collection", "el", "id", "attributes", "className", "tagName", "events"];
	_.extend(View.prototype, Events, {
		tagName: "div",
		$: function(selector) {
			return this.$el.find(selector)
		},
		initialize: function() {},
		render: function() {
			return this
		},
		remove: function() {
			this.$el.remove();
			this.stopListening();
			return this
		},
		setElement: function(element, delegate) {
			if (this.$el) this.undelegateEvents();
			this.$el = element instanceof Backbone.$ ? element : Backbone.$(element);
			this.el = this.$el[0];
			if (delegate !== false) this.delegateEvents();
			return this
		},
		delegateEvents: function(events) {
			if (!(events || (events = _.result(this, "events")))) return this;
			this.undelegateEvents();
			for (var key in events) {
				var method = events[key];
				if (!_.isFunction(method)) method = this[events[key]];
				if (!method) continue;
				var match = key.match(delegateEventSplitter);
				var eventName = match[1],
					selector = match[2];
				method = _.bind(method, this);
				eventName += ".delegateEvents" + this.cid;
				if (selector === "") {
					this.$el.on(eventName, method)
				} else {
					this.$el.on(eventName, selector, method)
				}
			}
			return this
		},
		undelegateEvents: function() {
			this.$el.off(".delegateEvents" + this.cid);
			return this
		},
		_configure: function(options) {
			if (this.options) options = _.extend({}, _.result(this, "options"), options);
			_.extend(this, _.pick(options, viewOptions));
			this.options = options
		},
		_ensureElement: function() {
			if (!this.el) {
				var attrs = _.extend({}, _.result(this, "attributes"));
				if (this.id) attrs.id = _.result(this, "id");
				if (this.className) attrs["class"] = _.result(this, "className");
				var $el = Backbone.$("<" + _.result(this, "tagName") + ">").attr(attrs);
				this.setElement($el, false)
			} else {
				this.setElement(_.result(this, "el"), false)
			}
		}
	});
	Backbone.sync = function(method, model, options) {
		var type = methodMap[method];
		_.defaults(options || (options = {}), {
			emulateHTTP: Backbone.emulateHTTP,
			emulateJSON: Backbone.emulateJSON
		});
		var params = {
			type: type,
			dataType: "json"
		};
		if (!options.url) {
			params.url = _.result(model, "url") || urlError()
		}
		if (options.data == null && model && (method === "create" || method === "update" || method === "patch")) {
			params.contentType = "application/json";
			params.data = JSON.stringify(options.attrs || model.toJSON(options))
		}
		if (options.emulateJSON) {
			params.contentType = "application/x-www-form-urlencoded";
			params.data = params.data ? {
				model: params.data
			} : {}
		}
		if (options.emulateHTTP && (type === "PUT" || type === "DELETE" || type === "PATCH")) {
			params.type = "POST";
			if (options.emulateJSON) params.data._method = type;
			var beforeSend = options.beforeSend;
			options.beforeSend = function(xhr) {
				xhr.setRequestHeader("X-HTTP-Method-Override", type);
				if (beforeSend) return beforeSend.apply(this, arguments)
			}
		}
		if (params.type !== "GET" && !options.emulateJSON) {
			params.processData = false
		}
		if (params.type === "PATCH" && window.ActiveXObject && !(window.external && window.external.msActiveXFilteringEnabled)) {
			params.xhr = function() {
				return new ActiveXObject("Microsoft.XMLHTTP")
			}
		}
		var xhr = options.xhr = Backbone.ajax(_.extend(params, options));
		model.trigger("request", model, xhr, options);
		return xhr
	};
	var methodMap = {
		create: "POST",
		update: "PUT",
		patch: "PATCH",
		"delete": "DELETE",
		read: "GET"
	};
	Backbone.ajax = function() {
		return Backbone.$.ajax.apply(Backbone.$, arguments)
	};
	var Router = Backbone.Router = function(options) {
		options || (options = {});
		if (options.routes) this.routes = options.routes;
		this._bindRoutes();
		this.initialize.apply(this, arguments)
	};
	var optionalParam = /\((.*?)\)/g;
	var namedParam = /(\(\?)?:\w+/g;
	var splatParam = /\*\w+/g;
	var escapeRegExp = /[\-{}\[\]+?.,\\\^$|#\s]/g;
	_.extend(Router.prototype, Events, {
		initialize: function() {},
		route: function(route, name, callback) {
			if (!_.isRegExp(route)) route = this._routeToRegExp(route);
			if (_.isFunction(name)) {
				callback = name;
				name = ""
			}
			if (!callback) callback = this[name];
			var router = this;
			Backbone.history.route(route, function(fragment) {
				var args = router._extractParameters(route, fragment);
				callback && callback.apply(router, args);
				router.trigger.apply(router, ["route:" + name].concat(args));
				router.trigger("route", name, args);
				Backbone.history.trigger("route", router, name, args)
			});
			return this
		},
		navigate: function(fragment, options) {
			Backbone.history.navigate(fragment, options);
			return this
		},
		_bindRoutes: function() {
			if (!this.routes) return;
			this.routes = _.result(this, "routes");
			var route, routes = _.keys(this.routes);
			while ((route = routes.pop()) != null) {
				this.route(route, this.routes[route])
			}
		},
		_routeToRegExp: function(route) {
			route = route.replace(escapeRegExp, "\\$&").replace(optionalParam, "(?:$1)?").replace(namedParam, function(match, optional) {
				return optional ? match : "([^/]+)"
			}).replace(splatParam, "(.*?)");
			return new RegExp("^" + route + "$")
		},
		_extractParameters: function(route, fragment) {
			var params = route.exec(fragment).slice(1);
			return _.map(params, function(param) {
				return param ? decodeURIComponent(param) : null
			})
		}
	});
	var History = Backbone.History = function() {
		this.handlers = [];
		_.bindAll(this, "checkUrl");
		if (typeof window !== "undefined") {
			this.location = window.location;
			this.history = window.history
		}
	};
	var routeStripper = /^[#\/]|\s+$/g;
	var rootStripper = /^\/+|\/+$/g;
	var isExplorer = /msie [\w.]+/;
	var trailingSlash = /\/$/;
	History.started = false;
	_.extend(History.prototype, Events, {
		interval: 50,
		getHash: function(window) {
			var match = (window || this).location.href.match(/#(.*)$/);
			return match ? match[1] : ""
		},
		getFragment: function(fragment, forcePushState) {
			if (fragment == null) {
				if (this._hasPushState || !this._wantsHashChange || forcePushState) {
					fragment = this.location.pathname;
					var root = this.root.replace(trailingSlash, "");
					if (!fragment.indexOf(root)) fragment = fragment.substr(root.length)
				} else {
					fragment = this.getHash()
				}
			}
			return fragment.replace(routeStripper, "")
		},
		start: function(options) {
			if (History.started) throw new Error("Backbone.history has already been started");
			History.started = true;
			this.options = _.extend({}, {
				root: "/"
			}, this.options, options);
			this.root = this.options.root;
			this._wantsHashChange = this.options.hashChange !== false;
			this._wantsPushState = !! this.options.pushState;
			this._hasPushState = !! (this.options.pushState && this.history && this.history.pushState);
			var fragment = this.getFragment();
			var docMode = document.documentMode;
			var oldIE = isExplorer.exec(navigator.userAgent.toLowerCase()) && (!docMode || docMode <= 7);
			this.root = ("/" + this.root + "/").replace(rootStripper, "/");
			if (oldIE && this._wantsHashChange) {
				this.iframe = Backbone.$('<iframe src="javascript:0" tabindex="-1" />').hide().appendTo("body")[0].contentWindow;
				this.navigate(fragment)
			}
			if (this._hasPushState) {
				Backbone.$(window).on("popstate", this.checkUrl)
			} else if (this._wantsHashChange && "onhashchange" in window && !oldIE) {
				Backbone.$(window).on("hashchange", this.checkUrl)
			} else if (this._wantsHashChange) {
				this._checkUrlInterval = setInterval(this.checkUrl, this.interval)
			}
			this.fragment = fragment;
			var loc = this.location;
			var atRoot = loc.pathname.replace(/[^\/]$/, "$&/") === this.root;
			if (this._wantsHashChange && this._wantsPushState && !this._hasPushState && !atRoot) {
				this.fragment = this.getFragment(null, true);
				this.location.replace(this.root + this.location.search + "#" + this.fragment);
				return true
			} else if (this._wantsPushState && this._hasPushState && atRoot && loc.hash) {
				this.fragment = this.getHash().replace(routeStripper, "");
				this.history.replaceState({}, document.title, this.root + this.fragment + loc.search)
			}
			if (!this.options.silent) return this.loadUrl()
		},
		stop: function() {
			Backbone.$(window).off("popstate", this.checkUrl).off("hashchange", this.checkUrl);
			clearInterval(this._checkUrlInterval);
			History.started = false
		},
		route: function(route, callback) {
			this.handlers.unshift({
				route: route,
				callback: callback
			})
		},
		checkUrl: function(e) {
			var current = this.getFragment();
			if (current === this.fragment && this.iframe) {
				current = this.getFragment(this.getHash(this.iframe))
			}
			if (current === this.fragment) return false;
			if (this.iframe) this.navigate(current);
			this.loadUrl() || this.loadUrl(this.getHash())
		},
		loadUrl: function(fragmentOverride) {
			var fragment = this.fragment = this.getFragment(fragmentOverride);
			var matched = _.any(this.handlers, function(handler) {
				if (handler.route.test(fragment)) {
					handler.callback(fragment);
					return true
				}
			});
			return matched
		},
		navigate: function(fragment, options) {
			if (!History.started) return false;
			if (!options || options === true) options = {
				trigger: options
			};
			fragment = this.getFragment(fragment || "");
			if (this.fragment === fragment) return;
			this.fragment = fragment;
			var url = this.root + fragment;
			if (this._hasPushState) {
				this.history[options.replace ? "replaceState" : "pushState"]({}, document.title, url)
			} else if (this._wantsHashChange) {
				this._updateHash(this.location, fragment, options.replace);
				if (this.iframe && fragment !== this.getFragment(this.getHash(this.iframe))) {
					if (!options.replace) this.iframe.document.open().close();
					this._updateHash(this.iframe.location, fragment, options.replace)
				}
			} else {
				return this.location.assign(url)
			} if (options.trigger) this.loadUrl(fragment)
		},
		_updateHash: function(location, fragment, replace) {
			if (replace) {
				var href = location.href.replace(/(javascript:|#).*$/, "");
				location.replace(href + "#" + fragment)
			} else {
				location.hash = "#" + fragment
			}
		}
	});
	Backbone.history = new History;
	var extend = function(protoProps, staticProps) {
		var parent = this;
		var child;
		if (protoProps && _.has(protoProps, "constructor")) {
			child = protoProps.constructor
		} else {
			child = function() {
				return parent.apply(this, arguments)
			}
		}
		_.extend(child, parent, staticProps);
		var Surrogate = function() {
			this.constructor = child
		};
		Surrogate.prototype = parent.prototype;
		child.prototype = new Surrogate;
		if (protoProps) _.extend(child.prototype, protoProps);
		child.__super__ = parent.prototype;
		return child
	};
	Model.extend = Collection.extend = Router.extend = View.extend = History.extend = extend;
	var urlError = function() {
		throw new Error('A "url" property or function must be specified')
	};
	var wrapError = function(model, options) {
		var error = options.error;
		options.error = function(resp) {
			if (error) error(model, resp, options);
			model.trigger("error", model, resp, options)
		}
	}
}.call(this);
_.extend(Backbone.Model.prototype, {
	sync: _.wrap(Backbone.Model.prototype.sync, function() {
		var args;
		args = Array.prototype.slice.call(arguments, 1);
		if (this.storeName) {
			var _this = this;
			if (args[0] === "read") {
				if (typeof syncStore !== "undefined") {
					syncStore.get(this.storeName, function(data) {
						args[2].success(data[_this.storeName] || {})
					})
				}
			} else if (args[0] === "create") {
				data = {};
				data[this.storeName] = this.toJSON();
				if (typeof syncStore !== "undefined") {
					syncStore.set(data, function() {
						args[2].success(data[_this.storeName])
					})
				}
			}
		} else {
			return arguments[0].apply(this, args)
		}
	})
});
! function(root, factory) {
	if (typeof exports === "object" && exports) {
		module.exports = factory
	} else if (typeof define === "function" && define.amd) {
		define(factory)
	} else {
		root.Mustache = factory
	}
}(this, function() {
	var exports = {};
	exports.name = "mustache.js";
	exports.version = "0.7.2";
	exports.tags = ["{{", "}}"];
	exports.Scanner = Scanner;
	exports.Context = Context;
	exports.Writer = Writer;
	var whiteRe = /\s*/;
	var spaceRe = /\s+/;
	var nonSpaceRe = /\S/;
	var eqRe = /\s*=/;
	var curlyRe = /\s*\}/;
	var tagRe = /#|\^|\/|>|\{|&|=|!/;

	function testRe(re, string) {
		return RegExp.prototype.test.call(re, string)
	}

	function isWhitespace(string) {
		return !testRe(nonSpaceRe, string)
	}
	var isArray = Array.isArray || function(obj) {
			return Object.prototype.toString.call(obj) === "[object Array]"
		};

	function escapeRe(string) {
		return string.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&")
	}
	var entityMap = {
		"&": "&amp;",
		"<": "&lt;",
		">": "&gt;",
		'"': "&quot;",
		"'": "&#39;",
		"/": "&#x2F;"
	};

	function escapeHtml(string) {
		return String(string).replace(/[&<>"'\/]/g, function(s) {
			return entityMap[s]
		})
	}
	exports.escape = escapeHtml;

	function Scanner(string) {
		this.string = string;
		this.tail = string;
		this.pos = 0
	}
	Scanner.prototype.eos = function() {
		return this.tail === ""
	};
	Scanner.prototype.scan = function(re) {
		var match = this.tail.match(re);
		if (match && match.index === 0) {
			this.tail = this.tail.substring(match[0].length);
			this.pos += match[0].length;
			return match[0]
		}
		return ""
	};
	Scanner.prototype.scanUntil = function(re) {
		var match, pos = this.tail.search(re);
		switch (pos) {
			case -1:
				match = this.tail;
				this.pos += this.tail.length;
				this.tail = "";
				break;
			case 0:
				match = "";
				break;
			default:
				match = this.tail.substring(0, pos);
				this.tail = this.tail.substring(pos);
				this.pos += pos
		}
		return match
	};

	function Context(view, parent) {
		this.view = view;
		this.parent = parent;
		this.clearCache()
	}
	Context.make = function(view) {
		return view instanceof Context ? view : new Context(view)
	};
	Context.prototype.clearCache = function() {
		this._cache = {}
	};
	Context.prototype.push = function(view) {
		return new Context(view, this)
	};
	Context.prototype.lookup = function(name) {
		var value = this._cache[name];
		if (!value) {
			if (name === ".") {
				value = this.view
			} else {
				var context = this;
				while (context) {
					if (name.indexOf(".") > 0) {
						var names = name.split("."),
							i = 0;
						value = context.view;
						while (value && i < names.length) {
							value = value[names[i++]]
						}
					} else {
						value = context.view[name]
					} if (value != null) {
						break
					}
					context = context.parent
				}
			}
			this._cache[name] = value
		}
		if (typeof value === "function") {
			value = value.call(this.view)
		}
		return value
	};

	function Writer() {
		this.clearCache()
	}
	Writer.prototype.clearCache = function() {
		this._cache = {};
		this._partialCache = {}
	};
	Writer.prototype.compile = function(template, tags) {
		var fn = this._cache[template];
		if (!fn) {
			var tokens = exports.parse(template, tags);
			fn = this._cache[template] = this.compileTokens(tokens, template)
		}
		return fn
	};
	Writer.prototype.compilePartial = function(name, template, tags) {
		var fn = this.compile(template, tags);
		this._partialCache[name] = fn;
		return fn
	};
	Writer.prototype.compileTokens = function(tokens, template) {
		var fn = compileTokens(tokens);
		var self = this;
		return function(view, partials) {
			if (partials) {
				if (typeof partials === "function") {
					self._loadPartial = partials
				} else {
					for (var name in partials) {
						self.compilePartial(name, partials[name])
					}
				}
			}
			return fn(self, Context.make(view), template)
		}
	};
	Writer.prototype.render = function(template, view, partials) {
		return this.compile(template)(view, partials)
	};
	Writer.prototype._section = function(name, context, text, callback) {
		var value = context.lookup(name);
		switch (typeof value) {
			case "object":
				if (isArray(value)) {
					var buffer = "";
					for (var i = 0, len = value.length; i < len; ++i) {
						buffer += callback(this, context.push(value[i]))
					}
					return buffer
				}
				return value ? callback(this, context.push(value)) : "";
			case "function":
				var self = this;
				var scopedRender = function(template) {
					return self.render(template, context)
				};
				var result = value.call(context.view, text, scopedRender);
				return result != null ? result : "";
			default:
				if (value) {
					return callback(this, context)
				}
		}
		return ""
	};
	Writer.prototype._inverted = function(name, context, callback) {
		var value = context.lookup(name);
		if (!value || isArray(value) && value.length === 0) {
			return callback(this, context)
		}
		return ""
	};
	Writer.prototype._partial = function(name, context) {
		if (!(name in this._partialCache) && this._loadPartial) {
			this.compilePartial(name, this._loadPartial(name))
		}
		var fn = this._partialCache[name];
		return fn ? fn(context) : ""
	};
	Writer.prototype._name = function(name, context) {
		var value = context.lookup(name);
		if (typeof value === "function") {
			value = value.call(context.view)
		}
		return value == null ? "" : String(value)
	};
	Writer.prototype._escaped = function(name, context) {
		return exports.escape(this._name(name, context))
	};

	function compileTokens(tokens) {
		var subRenders = {};

		function subRender(i, tokens, template) {
			if (!subRenders[i]) {
				var fn = compileTokens(tokens);
				subRenders[i] = function(writer, context) {
					return fn(writer, context, template)
				}
			}
			return subRenders[i]
		}
		return function(writer, context, template) {
			var buffer = "";
			var token, sectionText;
			for (var i = 0, len = tokens.length; i < len; ++i) {
				token = tokens[i];
				switch (token[0]) {
					case "#":
						sectionText = template.slice(token[3], token[5]);
						buffer += writer._section(token[1], context, sectionText, subRender(i, token[4], template));
						break;
					case "^":
						buffer += writer._inverted(token[1], context, subRender(i, token[4], template));
						break;
					case ">":
						buffer += writer._partial(token[1], context);
						break;
					case "&":
						buffer += writer._name(token[1], context);
						break;
					case "name":
						buffer += writer._escaped(token[1], context);
						break;
					case "text":
						buffer += token[1];
						break
				}
			}
			return buffer
		}
	}

	function nestTokens(tokens) {
		var tree = [];
		var collector = tree;
		var sections = [];
		var token;
		for (var i = 0, len = tokens.length; i < len; ++i) {
			token = tokens[i];
			switch (token[0]) {
				case "#":
				case "^":
					sections.push(token);
					collector.push(token);
					collector = token[4] = [];
					break;
				case "/":
					var section = sections.pop();
					section[5] = token[2];
					collector = sections.length > 0 ? sections[sections.length - 1][4] : tree;
					break;
				default:
					collector.push(token)
			}
		}
		return tree
	}

	function squashTokens(tokens) {
		var squashedTokens = [];
		var token, lastToken;
		for (var i = 0, len = tokens.length; i < len; ++i) {
			token = tokens[i];
			if (token[0] === "text" && lastToken && lastToken[0] === "text") {
				lastToken[1] += token[1];
				lastToken[3] = token[3]
			} else {
				lastToken = token;
				squashedTokens.push(token)
			}
		}
		return squashedTokens
	}

	function escapeTags(tags) {
		return [new RegExp(escapeRe(tags[0]) + "\\s*"), new RegExp("\\s*" + escapeRe(tags[1]))]
	}
	exports.parse = function(template, tags) {
		template = template || "";
		tags = tags || exports.tags;
		if (typeof tags === "string") tags = tags.split(spaceRe);
		if (tags.length !== 2) {
			throw new Error("Invalid tags: " + tags.join(", "))
		}
		var tagRes = escapeTags(tags);
		var scanner = new Scanner(template);
		var sections = [];
		var tokens = [];
		var spaces = [];
		var hasTag = false;
		var nonSpace = false;

		function stripSpace() {
			if (hasTag && !nonSpace) {
				while (spaces.length) {
					tokens.splice(spaces.pop(), 1)
				}
			} else {
				spaces = []
			}
			hasTag = false;
			nonSpace = false
		}
		var start, type, value, chr;
		while (!scanner.eos()) {
			start = scanner.pos;
			value = scanner.scanUntil(tagRes[0]);
			if (value) {
				for (var i = 0, len = value.length; i < len; ++i) {
					chr = value.charAt(i);
					if (isWhitespace(chr)) {
						spaces.push(tokens.length)
					} else {
						nonSpace = true
					}
					tokens.push(["text", chr, start, start + 1]);
					start += 1;
					if (chr === "\n") {
						stripSpace()
					}
				}
			}
			start = scanner.pos;
			if (!scanner.scan(tagRes[0])) {
				break
			}
			hasTag = true;
			type = scanner.scan(tagRe) || "name";
			scanner.scan(whiteRe);
			if (type === "=") {
				value = scanner.scanUntil(eqRe);
				scanner.scan(eqRe);
				scanner.scanUntil(tagRes[1])
			} else if (type === "{") {
				var closeRe = new RegExp("\\s*" + escapeRe("}" + tags[1]));
				value = scanner.scanUntil(closeRe);
				scanner.scan(curlyRe);
				scanner.scanUntil(tagRes[1]);
				type = "&"
			} else {
				value = scanner.scanUntil(tagRes[1])
			} if (!scanner.scan(tagRes[1])) {
				throw new Error("Unclosed tag at " + scanner.pos)
			}
			if (type === "/") {
				if (sections.length === 0) {
					throw new Error('Unopened section "' + value + '" at ' + start)
				}
				var section = sections.pop();
				if (section[1] !== value) {
					throw new Error('Unclosed section "' + section[1] + '" at ' + start)
				}
			}
			var token = [type, value, start, scanner.pos];
			tokens.push(token);
			if (type === "#" || type === "^") {
				sections.push(token)
			} else if (type === "name" || type === "{" || type === "&") {
				nonSpace = true
			} else if (type === "=") {
				tags = value.split(spaceRe);
				if (tags.length !== 2) {
					throw new Error("Invalid tags at " + start + ": " + tags.join(", "))
				}
				tagRes = escapeTags(tags)
			}
		}
		var section = sections.pop();
		if (section) {
			throw new Error('Unclosed section "' + section[1] + '" at ' + scanner.pos)
		}
		return nestTokens(squashTokens(tokens))
	};
	var _writer = new Writer;
	exports.clearCache = function() {
		return _writer.clearCache()
	};
	exports.compile = function(template, tags) {
		return _writer.compile(template, tags)
	};
	exports.compilePartial = function(name, template, tags) {
		return _writer.compilePartial(name, template, tags)
	};
	exports.compileTokens = function(tokens, template) {
		return _writer.compileTokens(tokens, template)
	};
	exports.render = function(template, view, partials) {
		return _writer.render(template, view, partials)
	};
	exports.to_html = function(template, view, partials, send) {
		var result = exports.render(template, view, partials);
		if (typeof send === "function") {
			send(result)
		} else {
			return result
		}
	};
	return exports
}());
! function(undefined) {
	var moment, VERSION = "1.7.2",
		round = Math.round,
		i, languages = {}, currentLanguage = "en",
		hasModule = typeof module !== "undefined" && module.exports,
		langConfigProperties = "months|monthsShort|weekdays|weekdaysShort|weekdaysMin|longDateFormat|calendar|relativeTime|ordinal|meridiem".split("|"),
		aspNetJsonRegex = /^\/?Date\((\-?\d+)/i,
		formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|YYYY|YY|a|A|hh?|HH?|mm?|ss?|SS?S?|zz?|ZZ?|.)/g,
		localFormattingTokens = /(\[[^\[]*\])|(\\)?(LT|LL?L?L?)/g,
		parseMultipleFormatChunker = /([0-9a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+)/gi,
		parseTokenOneOrTwoDigits = /\d\d?/,
		parseTokenOneToThreeDigits = /\d{1,3}/,
		parseTokenThreeDigits = /\d{3}/,
		parseTokenFourDigits = /\d{1,4}/,
		parseTokenWord = /[0-9a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+/i,
		parseTokenTimezone = /Z|[\+\-]\d\d:?\d\d/i,
		parseTokenT = /T/i,
		isoRegex = /^\s*\d{4}-\d\d-\d\d(T(\d\d(:\d\d(:\d\d(\.\d\d?\d?)?)?)?)?([\+\-]\d\d:?\d\d)?)?/,
		isoFormat = "YYYY-MM-DDTHH:mm:ssZ",
		isoTimes = [
			["HH:mm:ss.S", /T\d\d:\d\d:\d\d\.\d{1,3}/],
			["HH:mm:ss", /T\d\d:\d\d:\d\d/],
			["HH:mm", /T\d\d:\d\d/],
			["HH", /T\d\d/]
		],
		parseTimezoneChunker = /([\+\-]|\d\d)/gi,
		proxyGettersAndSetters = "Month|Date|Hours|Minutes|Seconds|Milliseconds".split("|"),
		unitMillisecondFactors = {
			Milliseconds: 1,
			Seconds: 1e3,
			Minutes: 6e4,
			Hours: 36e5,
			Days: 864e5,
			Months: 2592e6,
			Years: 31536e6
		}, formatFunctions = {}, ordinalizeTokens = "DDD w M D d".split(" "),
		paddedTokens = "M D H h m s w".split(" "),
		formatTokenFunctions = {
			M: function() {
				return this.month() + 1
			},
			MMM: function(format) {
				return getValueFromArray("monthsShort", this.month(), this, format)
			},
			MMMM: function(format) {
				return getValueFromArray("months", this.month(), this, format)
			},
			D: function() {
				return this.date()
			},
			DDD: function() {
				var a = new Date(this.year(), this.month(), this.date()),
					b = new Date(this.year(), 0, 1);
				return~~ ((a - b) / 864e5 + 1.5)
			},
			d: function() {
				return this.day()
			},
			dd: function(format) {
				return getValueFromArray("weekdaysMin", this.day(), this, format)
			},
			ddd: function(format) {
				return getValueFromArray("weekdaysShort", this.day(), this, format)
			},
			dddd: function(format) {
				return getValueFromArray("weekdays", this.day(), this, format)
			},
			w: function() {
				var a = new Date(this.year(), this.month(), this.date() - this.day() + 5),
					b = new Date(a.getFullYear(), 0, 4);
				return~~ ((a - b) / 864e5 / 7 + 1.5)
			},
			YY: function() {
				return leftZeroFill(this.year() % 100, 2)
			},
			YYYY: function() {
				return leftZeroFill(this.year(), 4)
			},
			a: function() {
				return this.lang().meridiem(this.hours(), this.minutes(), true)
			},
			A: function() {
				return this.lang().meridiem(this.hours(), this.minutes(), false)
			},
			H: function() {
				return this.hours()
			},
			h: function() {
				return this.hours() % 12 || 12
			},
			m: function() {
				return this.minutes()
			},
			s: function() {
				return this.seconds()
			},
			S: function() {
				return~~ (this.milliseconds() / 100)
			},
			SS: function() {
				return leftZeroFill(~~(this.milliseconds() / 10), 2)
			},
			SSS: function() {
				return leftZeroFill(this.milliseconds(), 3)
			},
			Z: function() {
				var a = -this.zone(),
					b = "+";
				if (a < 0) {
					a = -a;
					b = "-"
				}
				return b + leftZeroFill(~~(a / 60), 2) + ":" + leftZeroFill(~~a % 60, 2)
			},
			ZZ: function() {
				var a = -this.zone(),
					b = "+";
				if (a < 0) {
					a = -a;
					b = "-"
				}
				return b + leftZeroFill(~~(10 * a / 6), 4)
			}
		};

	function getValueFromArray(key, index, m, format) {
		var lang = m.lang();
		return lang[key].call ? lang[key](m, format) : lang[key][index]
	}

	function padToken(func, count) {
		return function(a) {
			return leftZeroFill(func.call(this, a), count)
		}
	}

	function ordinalizeToken(func) {
		return function(a) {
			var b = func.call(this, a);
			return b + this.lang().ordinal(b)
		}
	}
	while (ordinalizeTokens.length) {
		i = ordinalizeTokens.pop();
		formatTokenFunctions[i + "o"] = ordinalizeToken(formatTokenFunctions[i])
	}
	while (paddedTokens.length) {
		i = paddedTokens.pop();
		formatTokenFunctions[i + i] = padToken(formatTokenFunctions[i], 2)
	}
	formatTokenFunctions.DDDD = padToken(formatTokenFunctions.DDD, 3);

	function Moment(date, isUTC, lang) {
		this._d = date;
		this._isUTC = !! isUTC;
		this._a = date._a || null;
		this._lang = lang || false
	}

	function Duration(duration) {
		var data = this._data = {}, years = duration.years || duration.y || 0,
			months = duration.months || duration.M || 0,
			weeks = duration.weeks || duration.w || 0,
			days = duration.days || duration.d || 0,
			hours = duration.hours || duration.h || 0,
			minutes = duration.minutes || duration.m || 0,
			seconds = duration.seconds || duration.s || 0,
			milliseconds = duration.milliseconds || duration.ms || 0;
		this._milliseconds = milliseconds + seconds * 1e3 + minutes * 6e4 + hours * 36e5;
		this._days = days + weeks * 7;
		this._months = months + years * 12;
		data.milliseconds = milliseconds % 1e3;
		seconds += absRound(milliseconds / 1e3);
		data.seconds = seconds % 60;
		minutes += absRound(seconds / 60);
		data.minutes = minutes % 60;
		hours += absRound(minutes / 60);
		data.hours = hours % 24;
		days += absRound(hours / 24);
		days += weeks * 7;
		data.days = days % 30;
		months += absRound(days / 30);
		data.months = months % 12;
		years += absRound(months / 12);
		data.years = years;
		this._lang = false
	}

	function absRound(number) {
		if (number < 0) {
			return Math.ceil(number)
		} else {
			return Math.floor(number)
		}
	}

	function leftZeroFill(number, targetLength) {
		var output = number + "";
		while (output.length < targetLength) {
			output = "0" + output
		}
		return output
	}

	function addOrSubtractDurationFromMoment(mom, duration, isAdding) {
		var ms = duration._milliseconds,
			d = duration._days,
			M = duration._months,
			currentDate;
		if (ms) {
			mom._d.setTime(+mom + ms * isAdding)
		}
		if (d) {
			mom.date(mom.date() + d * isAdding)
		}
		if (M) {
			currentDate = mom.date();
			mom.date(1).month(mom.month() + M * isAdding).date(Math.min(currentDate, mom.daysInMonth()))
		}
	}

	function isArray(input) {
		return Object.prototype.toString.call(input) === "[object Array]"
	}

	function compareArrays(array1, array2) {
		var len = Math.min(array1.length, array2.length),
			lengthDiff = Math.abs(array1.length - array2.length),
			diffs = 0,
			i;
		for (i = 0; i < len; i++) {
			if (~~array1[i] !== ~~array2[i]) {
				diffs++
			}
		}
		return diffs + lengthDiff
	}

	function dateFromArray(input, asUTC, hoursOffset, minutesOffset) {
		var i, date, forValid = [];
		for (i = 0; i < 7; i++) {
			forValid[i] = input[i] = input[i] == null ? i === 2 ? 1 : 0 : input[i]
		}
		input[7] = forValid[7] = asUTC;
		if (input[8] != null) {
			forValid[8] = input[8]
		}
		input[3] += hoursOffset || 0;
		input[4] += minutesOffset || 0;
		date = new Date(0);
		if (asUTC) {
			date.setUTCFullYear(input[0], input[1], input[2]);
			date.setUTCHours(input[3], input[4], input[5], input[6])
		} else {
			date.setFullYear(input[0], input[1], input[2]);
			date.setHours(input[3], input[4], input[5], input[6])
		}
		date._a = forValid;
		return date
	}

	function loadLang(key, values) {
		var i, m, parse = [];
		if (!values && hasModule) {
			values = require("./lang/" + key)
		}
		for (i = 0; i < langConfigProperties.length; i++) {
			values[langConfigProperties[i]] = values[langConfigProperties[i]] || languages.en[langConfigProperties[i]]
		}
		for (i = 0; i < 12; i++) {
			m = moment([2e3, i]);
			parse[i] = new RegExp("^" + (values.months[i] || values.months(m, "")) + "|^" + (values.monthsShort[i] || values.monthsShort(m, "")).replace(".", ""), "i")
		}
		values.monthsParse = values.monthsParse || parse;
		languages[key] = values;
		return values
	}

	function getLangDefinition(m) {
		var langKey = typeof m === "string" && m || m && m._lang || null;
		return langKey ? languages[langKey] || loadLang(langKey) : moment
	}

	function removeFormattingTokens(input) {
		if (input.match(/\[.*\]/)) {
			return input.replace(/^\[|\]$/g, "")
		}
		return input.replace(/\\/g, "")
	}

	function makeFormatFunction(format) {
		var array = format.match(formattingTokens),
			i, length;
		for (i = 0, length = array.length; i < length; i++) {
			if (formatTokenFunctions[array[i]]) {
				array[i] = formatTokenFunctions[array[i]]
			} else {
				array[i] = removeFormattingTokens(array[i])
			}
		}
		return function(mom) {
			var output = "";
			for (i = 0; i < length; i++) {
				output += typeof array[i].call === "function" ? array[i].call(mom, format) : array[i]
			}
			return output
		}
	}

	function formatMoment(m, format) {
		var i = 5;

		function replaceLongDateFormatTokens(input) {
			return m.lang().longDateFormat[input] || input
		}
		while (i-- && localFormattingTokens.test(format)) {
			format = format.replace(localFormattingTokens, replaceLongDateFormatTokens)
		}
		if (!formatFunctions[format]) {
			formatFunctions[format] = makeFormatFunction(format)
		}
		return formatFunctions[format](m)
	}

	function getParseRegexForToken(token) {
		switch (token) {
			case "DDDD":
				return parseTokenThreeDigits;
			case "YYYY":
				return parseTokenFourDigits;
			case "S":
			case "SS":
			case "SSS":
			case "DDD":
				return parseTokenOneToThreeDigits;
			case "MMM":
			case "MMMM":
			case "dd":
			case "ddd":
			case "dddd":
			case "a":
			case "A":
				return parseTokenWord;
			case "Z":
			case "ZZ":
				return parseTokenTimezone;
			case "T":
				return parseTokenT;
			case "MM":
			case "DD":
			case "YY":
			case "HH":
			case "hh":
			case "mm":
			case "ss":
			case "M":
			case "D":
			case "d":
			case "H":
			case "h":
			case "m":
			case "s":
				return parseTokenOneOrTwoDigits;
			default:
				return new RegExp(token.replace("\\", ""))
		}
	}

	function addTimeToArrayFromToken(token, input, datePartArray, config) {
		var a, b;
		switch (token) {
			case "M":
			case "MM":
				datePartArray[1] = input == null ? 0 : ~~input - 1;
				break;
			case "MMM":
			case "MMMM":
				for (a = 0; a < 12; a++) {
					if (getLangDefinition().monthsParse[a].test(input)) {
						datePartArray[1] = a;
						b = true;
						break
					}
				}
				if (!b) {
					datePartArray[8] = false
				}
				break;
			case "D":
			case "DD":
			case "DDD":
			case "DDDD":
				if (input != null) {
					datePartArray[2] = ~~input
				}
				break;
			case "YY":
				datePartArray[0] = ~~input + (~~input > 70 ? 1900 : 2e3);
				break;
			case "YYYY":
				datePartArray[0] = ~~Math.abs(input);
				break;
			case "a":
			case "A":
				config.isPm = (input + "").toLowerCase() === "pm";
				break;
			case "H":
			case "HH":
			case "h":
			case "hh":
				datePartArray[3] = ~~input;
				break;
			case "m":
			case "mm":
				datePartArray[4] = ~~input;
				break;
			case "s":
			case "ss":
				datePartArray[5] = ~~input;
				break;
			case "S":
			case "SS":
			case "SSS":
				datePartArray[6] = ~~ (("0." + input) * 1e3);
				break;
			case "Z":
			case "ZZ":
				config.isUTC = true;
				a = (input + "").match(parseTimezoneChunker);
				if (a && a[1]) {
					config.tzh = ~~a[1]
				}
				if (a && a[2]) {
					config.tzm = ~~a[2]
				}
				if (a && a[0] === "+") {
					config.tzh = -config.tzh;
					config.tzm = -config.tzm
				}
				break
		}
		if (input == null) {
			datePartArray[8] = false
		}
	}

	function makeDateFromStringAndFormat(string, format) {
		var datePartArray = [0, 0, 1, 0, 0, 0, 0],
			config = {
				tzh: 0,
				tzm: 0
			}, tokens = format.match(formattingTokens),
			i, parsedInput;
		for (i = 0; i < tokens.length; i++) {
			parsedInput = (getParseRegexForToken(tokens[i]).exec(string) || [])[0];
			if (parsedInput) {
				string = string.slice(string.indexOf(parsedInput) + parsedInput.length)
			}
			if (formatTokenFunctions[tokens[i]]) {
				addTimeToArrayFromToken(tokens[i], parsedInput, datePartArray, config)
			}
		}
		if (config.isPm && datePartArray[3] < 12) {
			datePartArray[3] += 12
		}
		if (config.isPm === false && datePartArray[3] === 12) {
			datePartArray[3] = 0
		}
		return dateFromArray(datePartArray, config.isUTC, config.tzh, config.tzm)
	}

	function makeDateFromStringAndArray(string, formats) {
		var output, inputParts = string.match(parseMultipleFormatChunker) || [],
			formattedInputParts, scoreToBeat = 99,
			i, currentDate, currentScore;
		for (i = 0; i < formats.length; i++) {
			currentDate = makeDateFromStringAndFormat(string, formats[i]);
			formattedInputParts = formatMoment(new Moment(currentDate), formats[i]).match(parseMultipleFormatChunker) || [];
			currentScore = compareArrays(inputParts, formattedInputParts);
			if (currentScore < scoreToBeat) {
				scoreToBeat = currentScore;
				output = currentDate
			}
		}
		return output
	}

	function makeDateFromString(string) {
		var format = "YYYY-MM-DDT",
			i;
		if (isoRegex.exec(string)) {
			for (i = 0; i < 4; i++) {
				if (isoTimes[i][1].exec(string)) {
					format += isoTimes[i][0];
					break
				}
			}
			return parseTokenTimezone.exec(string) ? makeDateFromStringAndFormat(string, format + " Z") : makeDateFromStringAndFormat(string, format)
		}
		return new Date(string)
	}

	function substituteTimeAgo(string, number, withoutSuffix, isFuture, lang) {
		var rt = lang.relativeTime[string];
		return typeof rt === "function" ? rt(number || 1, !! withoutSuffix, string, isFuture) : rt.replace(/%d/i, number || 1)
	}

	function relativeTime(milliseconds, withoutSuffix, lang) {
		var seconds = round(Math.abs(milliseconds) / 1e3),
			minutes = round(seconds / 60),
			hours = round(minutes / 60),
			days = round(hours / 24),
			years = round(days / 365),
			args = seconds < 45 && ["s", seconds] || minutes === 1 && ["m"] || minutes < 45 && ["mm", minutes] || hours === 1 && ["h"] || hours < 22 && ["hh", hours] || days === 1 && ["d"] || days <= 25 && ["dd", days] || days <= 45 && ["M"] || days < 345 && ["MM", round(days / 30)] || years === 1 && ["y"] || ["yy", years];
		args[2] = withoutSuffix;
		args[3] = milliseconds > 0;
		args[4] = lang;
		return substituteTimeAgo.apply({}, args)
	}
	moment = function(input, format) {
		if (input === null || input === "") {
			return null
		}
		var date, matched;
		if (moment.isMoment(input)) {
			return new Moment(new Date(+input._d), input._isUTC, input._lang)
		} else if (format) {
			if (isArray(format)) {
				date = makeDateFromStringAndArray(input, format)
			} else {
				date = makeDateFromStringAndFormat(input, format)
			}
		} else {
			matched = aspNetJsonRegex.exec(input);
			date = input === undefined ? new Date : matched ? new Date(+matched[1]) : input instanceof Date ? input : isArray(input) ? dateFromArray(input) : typeof input === "string" ? makeDateFromString(input) : new Date(input)
		}
		return new Moment(date)
	};
	moment.utc = function(input, format) {
		if (isArray(input)) {
			return new Moment(dateFromArray(input, true), true)
		}
		if (typeof input === "string" && !parseTokenTimezone.exec(input)) {
			input += " +0000";
			if (format) {
				format += " Z"
			}
		}
		return moment(input, format).utc()
	};
	moment.unix = function(input) {
		return moment(input * 1e3)
	};
	moment.duration = function(input, key) {
		var isDuration = moment.isDuration(input),
			isNumber = typeof input === "number",
			duration = isDuration ? input._data : isNumber ? {} : input,
			ret;
		if (isNumber) {
			if (key) {
				duration[key] = input
			} else {
				duration.milliseconds = input
			}
		}
		ret = new Duration(duration);
		if (isDuration) {
			ret._lang = input._lang
		}
		return ret
	};
	moment.humanizeDuration = function(num, type, withSuffix) {
		return moment.duration(num, type === true ? null : type).humanize(type === true ? true : withSuffix)
	};
	moment.version = VERSION;
	moment.defaultFormat = isoFormat;
	moment.lang = function(key, values) {
		var i;
		if (!key) {
			return currentLanguage
		}
		if (values || !languages[key]) {
			loadLang(key, values)
		}
		if (languages[key]) {
			for (i = 0; i < langConfigProperties.length; i++) {
				moment[langConfigProperties[i]] = languages[key][langConfigProperties[i]]
			}
			moment.monthsParse = languages[key].monthsParse;
			currentLanguage = key
		}
	};
	moment.langData = getLangDefinition;
	moment.isMoment = function(obj) {
		return obj instanceof Moment
	};
	moment.isDuration = function(obj) {
		return obj instanceof Duration
	};
	moment.lang("en", {
		months: "January_February_March_April_May_June_July_August_September_October_November_December".split("_"),
		monthsShort: "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),
		weekdays: "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),
		weekdaysShort: "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),
		weekdaysMin: "Su_Mo_Tu_We_Th_Fr_Sa".split("_"),
		longDateFormat: {
			LT: "h:mm A",
			L: "MM/DD/YYYY",
			LL: "MMMM D YYYY",
			LLL: "MMMM D YYYY LT",
			LLLL: "dddd, MMMM D YYYY LT"
		},
		meridiem: function(hours, minutes, isLower) {
			if (hours > 11) {
				return isLower ? "pm" : "PM"
			} else {
				return isLower ? "am" : "AM"
			}
		},
		calendar: {
			sameDay: "[Today at] LT",
			nextDay: "[Tomorrow at] LT",
			nextWeek: "dddd [at] LT",
			lastDay: "[Yesterday at] LT",
			lastWeek: "[last] dddd [at] LT",
			sameElse: "L"
		},
		relativeTime: {
			future: "in %s",
			past: "%s ago",
			s: "a few seconds",
			m: "a minute",
			mm: "%d minutes",
			h: "an hour",
			hh: "%d hours",
			d: "a day",
			dd: "%d days",
			M: "a month",
			MM: "%d months",
			y: "a year",
			yy: "%d years"
		},
		ordinal: function(number) {
			var b = number % 10;
			return~~ (number % 100 / 10) === 1 ? "th" : b === 1 ? "st" : b === 2 ? "nd" : b === 3 ? "rd" : "th"
		}
	});
	moment.fn = Moment.prototype = {
		clone: function() {
			return moment(this)
		},
		valueOf: function() {
			return +this._d
		},
		unix: function() {
			return Math.floor(+this._d / 1e3)
		},
		toString: function() {
			return this._d.toString()
		},
		toDate: function() {
			return this._d
		},
		toArray: function() {
			var m = this;
			return [m.year(), m.month(), m.date(), m.hours(), m.minutes(), m.seconds(), m.milliseconds(), !! this._isUTC]
		},
		isValid: function() {
			if (this._a) {
				if (this._a[8] != null) {
					return !!this._a[8]
				}
				return !compareArrays(this._a, (this._a[7] ? moment.utc(this._a) : moment(this._a)).toArray())
			}
			return !isNaN(this._d.getTime())
		},
		utc: function() {
			this._isUTC = true;
			return this
		},
		local: function() {
			this._isUTC = false;
			return this
		},
		format: function(inputString) {
			return formatMoment(this, inputString ? inputString : moment.defaultFormat)
		},
		add: function(input, val) {
			var dur = val ? moment.duration(+val, input) : moment.duration(input);
			addOrSubtractDurationFromMoment(this, dur, 1);
			return this
		},
		subtract: function(input, val) {
			var dur = val ? moment.duration(+val, input) : moment.duration(input);
			addOrSubtractDurationFromMoment(this, dur, -1);
			return this
		},
		diff: function(input, val, asFloat) {
			var inputMoment = this._isUTC ? moment(input).utc() : moment(input).local(),
				zoneDiff = (this.zone() - inputMoment.zone()) * 6e4,
				diff = this._d - inputMoment._d - zoneDiff,
				year = this.year() - inputMoment.year(),
				month = this.month() - inputMoment.month(),
				date = this.date() - inputMoment.date(),
				output;
			if (val === "months") {
				output = year * 12 + month + date / 30
			} else if (val === "years") {
				output = year + (month + date / 30) / 12
			} else {
				output = val === "seconds" ? diff / 1e3 : val === "minutes" ? diff / 6e4 : val === "hours" ? diff / 36e5 : val === "days" ? diff / 864e5 : val === "weeks" ? diff / 6048e5 : diff
			}
			return asFloat ? output : round(output)
		},
		from: function(time, withoutSuffix) {
			return moment.duration(this.diff(time)).lang(this._lang).humanize(!withoutSuffix)
		},
		fromNow: function(withoutSuffix) {
			return this.from(moment(), withoutSuffix)
		},
		calendar: function() {
			var diff = this.diff(moment().sod(), "days", true),
				calendar = this.lang().calendar,
				allElse = calendar.sameElse,
				format = diff < -6 ? allElse : diff < -1 ? calendar.lastWeek : diff < 0 ? calendar.lastDay : diff < 1 ? calendar.sameDay : diff < 2 ? calendar.nextDay : diff < 7 ? calendar.nextWeek : allElse;
			return this.format(typeof format === "function" ? format.apply(this) : format)
		},
		isLeapYear: function() {
			var year = this.year();
			return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0
		},
		isDST: function() {
			return this.zone() < moment([this.year()]).zone() || this.zone() < moment([this.year(), 5]).zone()
		},
		day: function(input) {
			var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
			return input == null ? day : this.add({
				d: input - day
			})
		},
		startOf: function(val) {
			switch (val.replace(/s$/, "")) {
				case "year":
					this.month(0);
				case "month":
					this.date(1);
				case "day":
					this.hours(0);
				case "hour":
					this.minutes(0);
				case "minute":
					this.seconds(0);
				case "second":
					this.milliseconds(0)
			}
			return this
		},
		endOf: function(val) {
			return this.startOf(val).add(val.replace(/s?$/, "s"), 1).subtract("ms", 1)
		},
		sod: function() {
			return this.clone().startOf("day")
		},
		eod: function() {
			return this.clone().endOf("day")
		},
		zone: function() {
			return this._isUTC ? 0 : this._d.getTimezoneOffset()
		},
		daysInMonth: function() {
			return moment.utc([this.year(), this.month() + 1, 0]).date()
		},
		lang: function(lang) {
			if (lang === undefined) {
				return getLangDefinition(this)
			} else {
				this._lang = lang;
				return this
			}
		}
	};

	function makeGetterAndSetter(name, key) {
		moment.fn[name] = function(input) {
			var utc = this._isUTC ? "UTC" : "";
			if (input != null) {
				this._d["set" + utc + key](input);
				return this
			} else {
				return this._d["get" + utc + key]()
			}
		}
	}
	for (i = 0; i < proxyGettersAndSetters.length; i++) {
		makeGetterAndSetter(proxyGettersAndSetters[i].toLowerCase(), proxyGettersAndSetters[i])
	}
	makeGetterAndSetter("year", "FullYear");
	moment.duration.fn = Duration.prototype = {
		weeks: function() {
			return absRound(this.days() / 7)
		},
		valueOf: function() {
			return this._milliseconds + this._days * 864e5 + this._months * 2592e6
		},
		humanize: function(withSuffix) {
			var difference = +this,
				rel = this.lang().relativeTime,
				output = relativeTime(difference, !withSuffix, this.lang()),
				fromNow = difference <= 0 ? rel.past : rel.future;
			if (withSuffix) {
				if (typeof fromNow === "function") {
					output = fromNow(output)
				} else {
					output = fromNow.replace(/%s/i, output)
				}
			}
			return output
		},
		lang: moment.fn.lang
	};

	function makeDurationGetter(name) {
		moment.duration.fn[name] = function() {
			return this._data[name]
		}
	}

	function makeDurationAsGetter(name, factor) {
		moment.duration.fn["as" + name] = function() {
			return +this / factor
		}
	}
	for (i in unitMillisecondFactors) {
		if (unitMillisecondFactors.hasOwnProperty(i)) {
			makeDurationAsGetter(i, unitMillisecondFactors[i]);
			makeDurationGetter(i.toLowerCase())
		}
	}
	makeDurationAsGetter("Weeks", 6048e5);
	if (hasModule) {
		module.exports = moment
	}
	if (typeof ender === "undefined") {
		this["moment"] = moment
	}
	if (typeof define === "function" && define.amd) {
		define("moment", [], function() {
			return moment
		})
	}
}.call(this);
moment.fn.past = function(input, val) {
	input = input.charAt(0).toUpperCase() + input.slice(1);
	var back = function(date, occurrences) {
		if (date.format("dddd") != input) {
			return back(date.subtract("days", 1), occurrences)
		} else {
			if (occurrences === 0) {
				return moment(date.id())
			} else {
				return back(date.subtract("days", 1), occurrences - 1)
			}
		}
	};
	return back(moment(this).lang("en"), val)
};
moment.fn.id = function() {
	return this.format("M-D-YY")
};
var moduleKeywords, __indexOf = [].indexOf || function(item) {
		for (var i = 0, l = this.length; i < l; i++) {
			if (i in this && this[i] === item) return i
		}
		return -1
	};
moduleKeywords = ["extended", "included"];
Module = function() {
	function Module() {}
	Module.extend = function(obj) {
		var key, value, _ref;
		for (key in obj) {
			value = obj[key];
			if (__indexOf.call(moduleKeywords, key) < 0) {
				this[key] = value
			}
		}
		if ((_ref = obj.extended) != null) {
			_ref.apply(this)
		}
		return this
	};
	Module.include = function(obj) {
		var key, value, _ref;
		for (key in obj) {
			value = obj[key];
			if (__indexOf.call(moduleKeywords, key) < 0) {
				this.prototype[key] = value
			}
		}
		if ((_ref = obj.included) != null) {
			_ref.apply(this)
		}
		return this
	};
	return Module
}();
if (typeof Backbone != "undefined") {
	Backbone.Model.include = Backbone.View.include = Backbone.Collection.include = Module.include
}
BH.Base.include = Module.include;
var _gaq = _gaq || [];
_gaq.push(["_setAccount", "UA-43186716-1"]);
! function() {
	var ga = document.createElement("script");
	ga.type = "text/javascript";
	ga.async = true;
	ga.src = "https://ssl.google-analytics.com/ga.js";
	var s = document.getElementsByTagName("script")[0];
	s.parentNode.insertBefore(ga, s)
}();
BH.Templates.app = "<div class='frame'>  <div class='mainview view'></div>  <div class='navigation'>    <h1>      <a href='#/'>        {{i18n_history_title}}      </a>    </h1>    <div class='menu_view'></div>    <ul class='menu'>      <li>        <a class='setting' href='#settings'>          {{i18n_settings_link}}        </a>      </li>    </ul>  </div></div>";
BH.Templates.credits = "<img class='logo' src='/images/medium_logo.png' /><h1 class='title'>{{i18n_credits_title}}</h1><div class='content-area'>  <div>{{{i18n_developed_by}}}</div>  <h3>Open source frameworks in use</h3>  <ul class='open_source'>    <li>      <a href='http://backbonejs.org/'>Backbone</a>    </li>    <li>      <a href='http://documentcloud.github.com/underscore/'>Underscore</a>    </li>    <li>      <a href='http://zeptojs.com/'>Zepto</a>    </li>    <li>      <a href='https://github.com/janl/mustache.js/'>Mustache.js</a>    </li>    <li>      <a href='http://momentjs.com/'>Moment.js</a>    </li>    <li>      <a href='https://github.com/roykolak/chrome-bootstrap'>Chrome Bootstrap</a>    </li>  </ul>  <h3>{{i18n_translators_heading}}</h3>  <div>    <ul class='translators'>      <li>        <a href='http://twitter.com/laucmar'>Laura Martínez</a>        <div class='language'>{{i18n_spanish}}</div>      </li>      <li>        <a href='http://gplus.to/dfakhriev'>Damir Fakhriev</a>        <div class='language'>{{i18n_russian}}</div>      </li>      <li>        <a href='https://plus.google.com/115314774787477379472'>Filipe Catalão</a>        <div class='language'>{{i18n_portuguese}}</div>      </li>      <li>        <a href='http://theopenspring.com'>Gianluca Sangiovanni</a>        <div class='language'>{{i18n_italian}}</div>      </li>      <li>        <a href='mailto:tebai.hamza@gmail.com'>Hamza Tebai</a>        <div class='language'>{{i18n_french}}</div>      </li>      <li>        <a href='http://about.me/henrikcederblad'>Henrik Cederblad</a>        <div class='language'>{{i18n_swedish}}</div>      </li>      <li>        <a href='https://plus.google.com/u/0/115959812130668207635/posts'>PBB</a>        <div class='language'>{{i18n_chinese_simplified}}</div>      </li>    </ul>    <ul class='translators'>      <li>        <a href='http://twitter.com/kurtextrem'>Jacob G</a>        <div class='language'>{{i18n_german}}</div>      </li>      <li>        <a href='http://www.jedlikowski.com'>Przemek Jedlikowski</a>        <div class='language'>{{i18n_polish}}</div>      </li>      <li>        <a href='https://twitter.com/yl_ksa'>Wael M. Hazzazi</a>        <div class='language'>{{i18n_arabic}}</div>      </li>      <li>        <a href='http://twitter.com/HowManyFiles'>ハウメニ</a>        <div class='language'>{{i18n_japanese}}</div>      </li>      <li>        <a href='http://facebook.com/khaister'>Khai Nguyen</a>        <div class='language'>{{i18n_vietnamese}}</div>      </li>      <li>        Juanjo Teruel        <div class='language'>{{i18n_catalonian}}</div>      </li>    </ul>  </div>  <h4>{{i18n_translation_help_heading}}</h4>  <p style='width:auto'>{{{i18n_translation_instructions}}}</p></div><div class='action-area'>  <div class='action-area-right'>    <div class='button-strip'>      <button class='button close'>{{i18n_close_button}}</button>    </div>  </div></div>";
BH.Templates.day = "<header>  <h1 class='title'>    {{{title}}}    <span class='sub_title'>{{formalDate}}</span>  </h1>  <div class='corner'>    <input class='search' placeholder='{{i18n_search_input_placeholder_text}}' tabindex='1' type='text' />  </div>  <div class='controls'>    <a class='text back_to_week' href='{{weekUrl}}'>      {{{i18n_back_to_week_link}}}    </a>    <div class='spacer'></div>    <button class='delete_day' disabled='disabled'>      {{i18n_delete_all_visits_for_filter_button}}    </button>  </div></header><div class='content'></div>";
BH.Templates.day_results = "<ol class='history'>  {{#history}}    <li class='interval' data-id='{{id}}'>      <header>        <h4 class='title'>{{time}}</h4>        <a class='delete_interval delete' href='#' title='{{i18n_prompt_delete_button}}'>          {{i18n_prompt_delete_button}}        </a>      </header>      <ol class='visits highlightable editable'>        {{#visits}}          {{#isGrouped}}            <li class='visit' data-id='{{id}}'>              <a href='{{url}}'>                <dl class='description' style='background-image: url(chrome://favicon/{{url}})'>                  <dt>{{domain}}</dt>                  <dd class='time'>{{time}}</dd>                  <dd class='toggle_grouping'>                    <span class='show_visits'>                      <span class='arrow arrow_collapse'></span>                      {{i18n_expand_button}}                    </span>                    <span class='hide_visits'>                      <span class='arrow arrow_expand'></span>                      {{i18n_collapse_button}}                    </span>                  </dd>                </dl>              </a>              <a class='search_domain action' href='#search/{{host}}'>{{i18n_search_by_domain}}</a>              <a class='delete_grouped_visit delete' href='#' title='{{i18n_prompt_delete_button}}'>{{i18n_prompt_delete_button}}</a>              <ol class='visits highlightable'>                {{#groupedVisits}}                  <li class='visit' data-id='{{id}}'>                    <a href='{{url}}'>                      <dl class='description' style='background-image: url(chrome://favicon/{{url}})'>                        <dt>{{{title}}}</dt>                        <dd class='time'>{{time}}</dd>                        <dd class='location'>{{host}}{{path}}</dd>                      </dl>                    </a>                    <a class='search_domain action' href='#search/{{host}}'>{{i18n_search_by_domain}}</a>                    <a class='delete_visit delete' href='#' title='{{i18n_prompt_delete_button}}'>{{i18n_prompt_delete_button}}</a>                  </li>                {{/groupedVisits}}              </ol>            </li>          {{/isGrouped}}          {{^isGrouped}}            <li class='visit' data-id='{{id}}'>              <a href='{{url}}'>                <dl class='description' style='background-image: url(chrome://favicon/{{url}})'>                  <dt>{{{title}}}</dt>                  <dd class='time'>{{time}}</dd>                  <dd class='location'>{{host}}{{path}}</dd>                </dl>              </a>              <a class='search_domain action' href='#search/{{host}}'>{{i18n_search_by_domain}}</a>              <a class='delete_visit delete' href='#' title='{{i18n_prompt_delete_button}}'>{{i18n_prompt_delete_button}}</a>            </li>          {{/isGrouped}}        {{/visits}}      </ol>    </li>  {{/history}}</ol>{{^history}}  <p>{{i18n_no_visits_found}}</p>{{/history}}";
BH.Templates.mailing_list = "<img class='logo' src='/images/medium_logo.png' /><h1 class='title'>{{i18n_mailing_list_title}}</h1><div class='content-area'>  <p>{{i18n_mailing_list_description}}</p>  <a href='http://mad.ly/signups/84938/join' target='_blank' id='join_mailing_list'>{{i18n_mailing_list_link}}</a>  <p><i>{{i18n_mailing_list_promise}}</i></p></div><div class='action-area'>  <a href='#'>{{i18n_leave_a_review}}</a>  <div class='action-area-right'>    <div class='button-strip'>      <button class='button close'>{{i18n_close_button}}</button>    </div>  </div></div>";
BH.Templates.menu = "<ul class='menu'>  {{#weeks}}    <li class='week' data-week-id='{{id}}'>      <a href='{{url}}'>        {{{shortTitle}}}      </a>    </li>  {{/weeks}}</ul>";
BH.Templates.modal = "<div class='overlay transparent' id='overlay'>  <div class='page'></div></div>";
BH.Templates.prompt = "<div class='spinner'></div><h1 class='title'>{{i18n_prompt_title}}</h1><div class='content-area'>{{{content}}}</div><div class='action-area'>  <div class='action-area-right'>    <div class='button-strip'>      <button class='no'>{{i18n_prompt_cancel_button}}</button>      <button class='yes'>{{i18n_prompt_delete_button}}</button>    </div>  </div></div>";
BH.Templates.search = "<header>  <h1>    <span class='title'>{{title}}</span>  </h1>  <div class='corner'>    <a href='#' class='delete'>cancel</a>    <input class='search' placeholder='{{i18n_search_input_placeholder_text}}' tabindex='1' type='text' />  </div>  <div class='controls'>    <div class='spinner'></div>    <div class='pagination' style='margin: 0; position: relative;'></div>    <div class='spacer'></div>    <button class='delete_all'>      {{i18n_delete_all_visits_for_search_button}}    </button>  </div></header><div class='fade'></div><div class='content'></div>";
BH.Templates.search_pagination = "<ol class='pagination {{paginationClass}}'>  {{#pages}}    <li>      <a href='{{url}}' data-page='{{number}}' class='{{className}}'>{{number}}</a>    </li>  {{/pages}}</ol><div class='number_of_visits'>{{i18n_number_of_visits}}</div>";
BH.Templates.search_results = "<ol class='visits highlightable editable'>  {{#visits}}    <li class='visit visit_view'>      <a data-id='{{id}}' href='{{url}}'>        <dl class='description' style='background-image: url(chrome://favicon/{{url}})'>          <dt>{{{title}}}</dt>          <dd class='location'>{{{location}}}</dd>          <dd>{{{time}}} | {{{extendedDate}}}</dd>        </dl>      </a>      <a class='delete_visit delete' href='#' title='{{i18n_prompt_delete_button}}'>{{i18n_prompt_delete_button}}</a>    </li>  {{/visits}}</ol>{{^visits}}  <p class='no_visits'>{{i18n_no_visits_found}}</p>{{/visits}}";
BH.Templates.settings = "<header>  <h1>{{i18n_settings_title}}</h1></header><div class='content'>  <div class='settings'>    <section>      <h3>{{i18n_clearing_history_section_title}}</h3>      <div>        <button class='clear_history'>{{i18n_clear_history_button}}</button>      </div>    </section>    <section>      <h3>{{i18n_general_section_title}}</h3>      <div class='row'>        <label>          <span class='select'>{{i18n_open_location}}</span>          <select id='open_location'>            {{#openLocations}}              <option value='{{value}}'>{{text}}</option>            {{/openLocations}}          </select>        </label>      </div>      <div class='row'>        <label>          <span class='select'>{{i18n_starting_week_day}}</span>          <select id='starting_week_day'>            {{#startingWeekDays}}              <option value='{{value}}'>{{text}}</option>            {{/startingWeekDays}}          </select>        </label>      </div>      <div class='row'>        <label>          <span class='select'>{{i18n_week_day_order}}</span>          <select id='week_day_order'>            {{#weekDayOrders}}              <option value='{{value}}'>{{text}}</option>            {{/weekDayOrders}}          </select>        </label>      </div>    </section>    <section>      <h3>{{i18n_visit_grouping_section_title}}</h3>      <div class='row'>        <label>          <span class='select'>{{i18n_group_visits_by_label}}</span>          <select id='time_grouping'>            {{#timeGroupings}}              <option value='{{value}}'>{{text}}</option>            {{/timeGroupings}}          </select>        </label>      </div>      <div class='checkbox'>        <label>          <input id='domain_grouping' type='checkbox' />          <span>{{i18n_group_visits_by_domain_label}}</span>        </label>      </div>    </section>    <section>      <h3>{{i18n_right_click_options_section_title}}</h3>      <div class='checkbox'>        <label>          <input id='search_by_selection' type='checkbox' />          <span>{{i18n_search_by_text_selection_label}}</span>        </label>      </div>      <div class='checkbox'>        <label>          <input id='search_by_domain' type='checkbox' />          <span>{{i18n_search_by_domain_label}}</span>        </label>      </div>    </section>     </div></div>";
BH.Templates.week = "<header>  <h1>{{{title}}}</h1>  <div class='corner'>    <input class='search' placeholder='{{i18n_search_input_placeholder_text}}' tabindex='1' type='text' />  </div>  <div class='controls'>    <span class='text count'></span>    <div class='spinner'></div>    <div class='spacer'></div>    <button class='delete_all'>      {{i18n_delete_all_visits_for_filter_button}}    </button>  </div></header><div class='content'>  <ol class='days'>    {{#days}}      <li class='day {{#inFuture}}future{{/inFuture}}' data-day='{{day}}'>        <a href='{{url}}'>          <div class='label'>            <h3 class='title'>{{title}}</h3>            <div class='count'></div>          </div>          <div class='bar_container'>            <div class='bar'></div>          </div>        </a>      </li>    {{/days}}  </ol></div><div class='day_views'></div>";
! function() {
	BH.Modules.I18n = {
		t: function(key, replacements) {
			var keys, lookup, _i, _len;
			if (replacements == null) {
				replacements = []
			}
			if (key instanceof Array) {
				keys = key;
				lookup = {};
				for (_i = 0, _len = keys.length; _i < _len; _i++) {
					key = keys[_i];
					lookup["i18n_" + key] = this.chromeAPI.i18n.getMessage(key.toString())
				}
				return lookup
			} else {
				return this.chromeAPI.i18n.getMessage(key, replacements)
			}
		}
	}
}.call(this);
! function() {
	BH.Modules.Url = {
		urlFor: function(key, id, opts) {
			var base, buildBase, route;
			base = "chrome://history/";
			if (key == null) {
				return base
			}
			buildBase = function(opts) {
				if (opts != null ? opts.absolute : void 0) {
					return base
				} else {
					return ""
				}
			};
			route = function() {
				switch (key) {
					case "search":
						return "#search/" + id;
					case "week":
						return "#weeks/" + id;
					case "day":
						return "#days/" + id
				}
			}();
			return "" + buildBase(opts) + route
		}
	}
}.call(this);
! function() {
	BH.Modules.Worker = {
		worker: function(name, options, callback) {
			var basePath, path, worker;
			basePath = "scripts/workers";
			path = function() {
				switch (name) {
					case "sanitizer":
						return "" + basePath + "/sanitizer.js";
					case "domainGrouper":
						return "" + basePath + "/domain_grouper.js";
					case "timeGrouper":
						return "" + basePath + "/time_grouper.js";
					case "dayGrouper":
						return "" + basePath + "/day_grouper.js"
				}
			}();
			worker = new Worker(path);
			worker.onmessage = function(e) {
				if (e.data.log) {
					return console.log(e.data.log)
				} else {
					callback(e.data);
					return worker.terminate()
				}
			};
			return worker.postMessage(options)
		}
	}
}.call(this);
! function() {
	BH.Trackers.ErrorTracker = function() {
		ErrorTracker.prototype.key = "eb2245d5729a3c65d7e429f4e7690a62";
		ErrorTracker.prototype.version = "1.16.11";
		ErrorTracker.prototype.environment = "production";

		function ErrorTracker(tracker) {
			this.tracker = tracker;
			this.tracker.configure({
				api_key: this.key,
				environment: this.environment,
				onerror: true
			})
		}
		ErrorTracker.prototype.report = function(e, data) {
			if (data == null) {
				data = {}
			}
			data.version = this.version;
			return this.tracker.notify(e, {
				context: data
			})
		};
		return ErrorTracker
	}()
}.call(this);
! function() {
	BH.Trackers.AnalyticsTracker = function() {
		function AnalyticsTracker(analytics) {
			if (analytics == null) {
				throw "Analytics not set"
			}
			this.analytics = analytics
		}
		AnalyticsTracker.prototype.pageView = function(url) {
			if (url.match(/search/)) {
				url = "search"
			}
			return this.analytics.push(["_trackPageview", "/" + url])
		};
		AnalyticsTracker.prototype.weekView = function(date, distanceFromCurrentWeek) {
			return this.trackEvent(["Weeks", "Click", date, distanceFromCurrentWeek])
		};
		AnalyticsTracker.prototype.visitDeletion = function() {
			return this.trackEvent(["Visit", "Delete"])
		};
		AnalyticsTracker.prototype.groupedVisitsDeletion = function() {
			return this.trackEvent(["Grouped visits", "Delete"])
		};
		AnalyticsTracker.prototype.timeIntervalDeletion = function() {
			return this.trackEvent(["Time interval", "Delete"])
		};
		AnalyticsTracker.prototype.dayVisitsDeletion = function() {
			return this.trackEvent(["Day visits", "Delete"])
		};
		AnalyticsTracker.prototype.weekVisitsDeletion = function() {
			return this.trackEvent(["Week visits", "Delete"])
		};
		AnalyticsTracker.prototype.searchResultsDeletion = function() {
			return this.trackEvent(["Search results", "Delete"])
		};
		AnalyticsTracker.prototype.paginationClick = function() {
			return this.trackEvent(["Pagination", "Click"])
		};
		AnalyticsTracker.prototype.omniboxSearch = function() {
			return this.trackEvent(["Omnibox", "Search"])
		};
		AnalyticsTracker.prototype.browserActionClick = function() {
			return this.trackEvent(["Browser action", "Click"])
		};
		AnalyticsTracker.prototype.contextMenuClick = function() {
			return this.trackEvent(["Context menu", "Click"])
		};
		AnalyticsTracker.prototype.selectionContextMenuClick = function() {
			return this.trackEvent(["Selection context menu", "Click"])
		};
		AnalyticsTracker.prototype.syncStorageError = function(operation, msg) {
			return this.trackEvent(["Storage Error", operation, "Sync", msg])
		};
		AnalyticsTracker.prototype.syncStorageAccess = function(operation) {
			return this.trackEvent(["Storage Access", operation, "Sync"])
		};
		AnalyticsTracker.prototype.mailingListPrompt = function() {
			return this.trackEvent(["Mailing List Prompt", "Seen"])
		};
		AnalyticsTracker.prototype.trackEvent = function(params) {
			params.unshift("_trackEvent");
			return this.analytics.push(params)
		};
		return AnalyticsTracker
	}()
}.call(this);
! function() {
	var __hasProp = {}.hasOwnProperty,
		__extends = function(child, parent) {
			for (var key in parent) {
				if (__hasProp.call(parent, key)) child[key] = parent[key]
			}

			function ctor() {
				this.constructor = child
			}
			ctor.prototype = parent.prototype;
			child.prototype = new ctor;
			child.__super__ = parent.prototype;
			return child
		};
	BH.Lib.DateI18n = function(_super) {
		__extends(DateI18n, _super);
		DateI18n.include(BH.Modules.I18n);

		function DateI18n() {
			this.moment = moment;
			this.chromeAPI = chrome
		}
		DateI18n.prototype.configure = function() {
			var _this = this;
			this.moment.lang(this.t("chrome_language"), {
				months: [this.t("january"), this.t("february"), this.t("march"), this.t("april"), this.t("may"), this.t("june"), this.t("july"), this.t("august"), this.t("september"), this.t("october"), this.t("november"), this.t("december")],
				weekdays: [this.t("sunday"), this.t("monday"), this.t("tuesday"), this.t("wednesday"), this.t("thursday"), this.t("friday"), this.t("saturday")],
				longDateFormat: {
					LT: this.t("local_time"),
					L: this.t("short_date"),
					LL: this.t("short_date_with_day"),
					LLL: this.t("formal_date")
				},
				meridiem: function(hour, minute, isLower) {
					if (hour < 12) {
						return _this.t("morning")
					} else if (hour >= 12 && hour < 16) {
						return _this.t("afternoon")
					} else if (hour >= 16) {
						return _this.t("evening")
					}
				},
				ordinal: function(number) {
					return _this.t("ordinal_" + number)
				}
			});
			return this.moment.lang(this.t("chrome_language"))
		};
		return DateI18n
	}(BH.Base)
}.call(this);
! function() {
	var __hasProp = {}.hasOwnProperty,
		__extends = function(child, parent) {
			for (var key in parent) {
				if (__hasProp.call(parent, key)) child[key] = parent[key]
			}

			function ctor() {
				this.constructor = child
			}
			ctor.prototype = parent.prototype;
			child.prototype = new ctor;
			child.__super__ = parent.prototype;
			return child
		};
	BH.Lib.HistoryQuery = function(_super) {
		__extends(HistoryQuery, _super);
		HistoryQuery.include(BH.Modules.Worker);
		HistoryQuery.include(BH.Modules.I18n);

		function HistoryQuery() {
			this.chromeAPI = chrome
		}
		HistoryQuery.prototype.run = function(options, callback) {
			var _this = this;
			this.options = options;
			if (this.options.text) {
				this.text = this.options.text;
				this.options.text = ""
			}
			options = {};
			_.extend(options, this.options);
			if (this.options.searching != null) {
				_.extend(options, this.searchOptions)
			} else {
				options.maxResults = 5e3
			}
			delete options.searching;
			return this.chromeAPI.history.search(options, function(results) {
				return _this.searchHandler(results, callback)
			})
		};
		HistoryQuery.prototype.searchHandler = function(results, callback) {
			if (this.text) {
				this.options.text = this.text
			}
			results = this._prepareResults(results);
			return this._sanitizeResults(results, callback)
		};
		HistoryQuery.prototype._sanitizeResults = function(results, callback) {
			var options;
			options = {
				options: this.options,
				results: results
			};
			return this.worker("sanitizer", options, callback)
		};
		HistoryQuery.prototype._prepareResults = function(results) {
			var _this = this;
			_(results).each(function(result) {
				result.date = new Date(result.lastVisitTime);
				result.extendedDate = moment(result.date).format(_this.t("extended_formal_date"));
				return result.time = moment(result.date).format(_this.t("local_time"))
			});
			return results
		};
		HistoryQuery.prototype.searchOptions = {
			startTime: 0,
			maxResults: 0
		};
		return HistoryQuery
	}(BH.Base)
}.call(this);
! function() {
	BH.Lib.Pagination = {
		RESULTS_PER_PAGE: 100,
		calculatePages: function(resultAmount) {
			return Math.ceil(resultAmount / this.RESULTS_PER_PAGE)
		},
		calculateBounds: function(page) {
			var end, start;
			start = page * this.RESULTS_PER_PAGE;
			end = page === 0 ? this.RESULTS_PER_PAGE : page * this.RESULTS_PER_PAGE + this.RESULTS_PER_PAGE;
			return [start, end]
		}
	}
}.call(this);
! function() {
	BH.Lib.SyncStore = function() {
		function SyncStore(options) {
			if (options == null) {
				options = {}
			}
			if (options.chrome == null) {
				throw "Chrome API not set"
			}
			if (options.tracker == null) {
				throw "Tracker not set"
			}
			this.chromeAPI = options.chrome;
			this.tracker = options.tracker
		}
		SyncStore.prototype.set = function(object, callback) {
			var _this = this;
			if (callback == null) {
				callback = function() {}
			}
			return this.chromeAPI.storage.sync.set(object, function(data) {
				return _this.wrappedCallback("Set", data, callback)
			})
		};
		SyncStore.prototype.remove = function(key, callback) {
			var _this = this;
			if (callback == null) {
				callback = function() {}
			}
			return this.chromeAPI.storage.sync.remove(key, function(data) {
				return _this.wrappedCallback("Remove", data, callback)
			})
		};
		SyncStore.prototype.get = function(key, callback) {
			var _this = this;
			return this.chromeAPI.storage.sync.get(key, function(data) {
				return _this.wrappedCallback("Get", data, callback)
			})
		};
		SyncStore.prototype.wrappedCallback = function(operation, data, callback) {
			var message, _ref;
			if (data == null) {
				data = {}
			}
			if (this.chromeAPI.runtime.lastError != null) {
				message = (_ref = this.chromeAPI.runtime.lastError) != null ? _ref.message : void 0;
				this.tracker.syncStorageError(operation, message)
			} else {
				if (operation !== "Get") {
					this.tracker.syncStorageAccess(operation)
				}
			}
			return callback(data)
		};
		return SyncStore
	}()
}.call(this);
! function() {
	var __hasProp = {}.hasOwnProperty,
		__extends = function(child, parent) {
			for (var key in parent) {
				if (__hasProp.call(parent, key)) child[key] = parent[key]
			}

			function ctor() {
				this.constructor = child
			}
			ctor.prototype = parent.prototype;
			child.prototype = new ctor;
			child.__super__ = parent.prototype;
			return child
		};
	BH.Views.ModalView = function(_super) {
		__extends(ModalView, _super);

		function ModalView() {
			return ModalView.__super__.constructor.apply(this, arguments)
		}
		ModalView.prototype.pulseClass = "pulse";
		ModalView.prototype.generalEvents = {
			"click .close-button": "close",
			"click .overlay": "overlayClicked"
		};
		ModalView.prototype.attachGeneralEvents = function() {
			return _.extend(this.events, this.generalEvents)
		};
		ModalView.prototype.renderTemplate = function(json) {
			var overlay;
			overlay = $(BH.Templates["modal"]);
			$(".page", overlay).append(Mustache.to_html(this.template, json));
			return overlay
		};
		ModalView.prototype.open = function() {
			$("body").append(this.render().el);
			this._globalBinds();
			$(window).trigger("resize");
			return setTimeout(function() {
				return this.$(".overlay").removeClass("transparent")
			}, 0)
		};
		ModalView.prototype.overlayClicked = function() {
			var _this = this;
			this.$(".page").addClass("pulse");
			return this.$(".page").on("webkitAnimationEnd", function() {
				return _this.$(".page").removeClass("pulse")
			})
		};
		ModalView.prototype.close = function() {
			var _this = this;
			this.trigger("close");
			this.$(".overlay").addClass("transparent");
			setTimeout(function() {
				return _this.remove()
			}, 1e3);
			return this._globalUnbinds()
		};
		ModalView.prototype._globalBinds = function() {
			$(window).resize(this._updateHeight);
			return $(window).keydown($.proxy(this._closeOnEscape, this))
		};
		ModalView.prototype._globalUnbinds = function() {
			$(window).unbind("resize");
			return $(document).unbind("keydown")
		};
		ModalView.prototype._updateHeight = function() {
			return this.$(".page").css({
				maxHeight: Math.min(.9 * window.innerHeight, 640)
			})
		};
		ModalView.prototype._closeOnEscape = function(e) {
			if (e.keyCode === 27) {
				return this.close()
			}
		};
		return ModalView
	}(Backbone.View)
}.call(this);
! function() {
	var __hasProp = {}.hasOwnProperty,
		__extends = function(child, parent) {
			for (var key in parent) {
				if (__hasProp.call(parent, key)) child[key] = parent[key]
			}

			function ctor() {
				this.constructor = child
			}
			ctor.prototype = parent.prototype;
			child.prototype = new ctor;
			child.__super__ = parent.prototype;
			return child
		};
	BH.Views.MainView = function(_super) {
		__extends(MainView, _super);

		function MainView() {
			return MainView.__super__.constructor.apply(this, arguments)
		}
		MainView.prototype.select = function() {
			var cleanTitle, element, _this = this;
			$(".mainview > *").removeClass("selected");
			$(".mainview > *").css({
				display: "block"
			});
			setTimeout(function() {
				_this.$el.addClass("selected");
				return $(".mainview > *:not(.selected)").css({
					display: "none"
				})
			}, 0);
			if (this.pageTitle) {
				element = $("<div/>");
				cleanTitle = $(element).html(this.pageTitle()).text();
				document.title = "" + cleanTitle + " - Better History"
			}
			this.trigger("selected");
			return this
		};
		MainView.prototype.onSearchTyped = function(ev) {
			var term;
			term = this.trimedSearchTerm();
			if (ev.keyCode === 13 && term !== "") {
				return router.navigate("search/" + term, true)
			}
		};
		MainView.prototype.onSearchBlurred = function() {
			return this.$(".search").val(this.trimedSearchTerm())
		};
		MainView.prototype.trimedSearchTerm = function() {
			return $.trim(this.$(".search").val())
		};
		MainView.prototype.assignTabIndices = function(selector) {
			$("*").removeAttr("tabindex");
			this.$("input.search").attr("tabindex", 1);
			this.$(selector).each(function(i) {
				return $(this).attr("tabindex", i + 2)
			});
			return this.$(".search").focus()
		};
		return MainView
	}(Backbone.View)
}.call(this);
! function() {
	var __hasProp = {}.hasOwnProperty,
		__extends = function(child, parent) {
			for (var key in parent) {
				if (__hasProp.call(parent, key)) child[key] = parent[key]
			}

			function ctor() {
				this.constructor = child
			}
			ctor.prototype = parent.prototype;
			child.prototype = new ctor;
			child.__super__ = parent.prototype;
			return child
		};
	BH.Views.AppView = function(_super) {
		__extends(AppView, _super);

		function AppView() {
			return AppView.__super__.constructor.apply(this, arguments)
		}
		AppView.include(BH.Modules.I18n);
		AppView.prototype.className = "app_view";
		AppView.prototype.template = BH.Templates["app"];
		AppView.prototype.initialize = function() {
			this.chromeAPI = chrome;
			this.settings = this.options.settings;
			this.collection.reload(this.settings.get("startingWeekDay"));
			this.options.state.on("change", this.onStateChanged, this);
			this.settings.on("change:startingWeekDay", this.onStartingWeekDayChanged, this);
			this.settings.on("change:weekDayOrder", this.onWeekDayOrderChanged, this);
			this.collection.on("reloaded", this.onWeeksReloaded, this);
			return this.cache = new BH.Views.Cache(this.options)
		};
		AppView.prototype.render = function() {
			var html;
			html = Mustache.to_html(this.template, this.getI18nValues());
			this.$el.html(html);
			this.renderMenu();
			return this
		};
		AppView.prototype.renderMenu = function() {
			var menuView;
			menuView = new BH.Views.MenuView({
				el: ".menu_view",
				collection: this.collection
			});
			return menuView.render()
		};
		AppView.prototype.onStateChanged = function() {
			return this.options.state.save()
		};
		AppView.prototype.onStartingWeekDayChanged = function() {
			return this.reloadWeeks()
		};
		AppView.prototype.onWeeksReloaded = function() {
			return this.renderMenu()
		};
		AppView.prototype.onWeekDayOrderChanged = function() {
			this.reloadWeeks();
			return this.cache.expire()
		};
		AppView.prototype.reloadWeeks = function() {
			this.collection.reset();
			return this.collection.reload(this.settings.get("startingWeekDay"))
		};
		AppView.prototype.loadWeek = function(id) {
			this.updateMenuSelection(id);
			return this.cache.weekView(id)
		};
		AppView.prototype.loadDay = function(id) {
			var startingWeekDay, weekId;
			startingWeekDay = this.settings.get("startingWeekDay");
			weekId = moment(id).past(startingWeekDay, 0).id();
			this.updateMenuSelection(weekId);
			return this.cache.dayView(id)
		};
		AppView.prototype.loadSettings = function() {
			this.updateMenuSelection();
			this.$(".menu .setting").parent().addClass("selected");
			return this.cache.settingsView()
		};
		AppView.prototype.loadSearch = function(options) {
			if (options == null) {
				options = {}
			}
			this.updateMenuSelection();
			return this.cache.searchView(options)
		};
		AppView.prototype.updateMenuSelection = function(id) {
			this.$(".menu > *").removeClass("selected");
			if (id != null) {
				return this.$("[data-week-id='" + id + "']").addClass("selected")
			}
		};
		AppView.prototype.getI18nValues = function() {
			return this.t(["history_title", "settings_link"])
		};
		return AppView
	}(Backbone.View)
}.call(this);
! function() {
	BH.Views.Cache = function() {
		function Cache(options) {
			this.options = options;
			this.settings = this.options.settings;
			this.state = this.options.state;
			this.expire()
		}
		Cache.prototype.expire = function() {
			return this.cache = {
				weeks: {},
				days: {}
			}
		};
		Cache.prototype.weekView = function(id) {
			var history, week;
			if (!this.cache.weeks[id]) {
				week = new BH.Models.Week({
					date: moment(new Date(id))
				}, {
					settings: this.settings
				});
				history = new BH.Models.WeekHistory(week.toHistory());
				this.cache.weeks[id] = new BH.Views.WeekView({
					model: week,
					history: history
				});
				this.insert(this.cache.weeks[id].render().el)
			}
			return this.cache.weeks[id]
		};
		Cache.prototype.dayView = function(id) {
			var day, history;
			if (!this.cache.days[id]) {
				day = new BH.Models.Day({
					date: moment(new Date(id))
				}, {
					settings: this.settings
				});
				history = new BH.Models.DayHistory(day.toHistory(), {
					settings: this.settings
				});
				this.cache.days[id] = new BH.Views.DayView({
					model: day,
					history: history
				});
				this.insert(this.cache.days[id].render().el)
			}
			return this.cache.days[id]
		};
		Cache.prototype.searchView = function(options) {
			var history, search;
			if (!this.cache.search || options.expired) {
				search = new BH.Models.Search;
				history = new BH.Models.SearchHistory(search.toHistory());
				this.cache.search = new BH.Views.SearchView({
					model: search,
					history: history
				});
				this.insert(this.cache.search.render().el)
			}
			return this.cache.search
		};
		Cache.prototype.settingsView = function() {
			if (!this.cache.settings) {
				this.cache.settings = new BH.Views.SettingsView({
					model: this.settings,
					state: this.state
				});
				this.insert(this.cache.settings.render().el)
			}
			return this.cache.settings
		};
		Cache.prototype.insert = function(html) {
			return $(".mainview").append(html)
		};
		return Cache
	}()
}.call(this);
! function() {
	var __hasProp = {}.hasOwnProperty,
		__extends = function(child, parent) {
			for (var key in parent) {
				if (__hasProp.call(parent, key)) child[key] = parent[key]
			}

			function ctor() {
				this.constructor = child
			}
			ctor.prototype = parent.prototype;
			child.prototype = new ctor;
			child.__super__ = parent.prototype;
			return child
		};
	BH.Views.CreditsView = function(_super) {
		__extends(CreditsView, _super);

		function CreditsView() {
			return CreditsView.__super__.constructor.apply(this, arguments)
		}
		CreditsView.include(BH.Modules.I18n);
		CreditsView.prototype.className = "credits_view";
		CreditsView.prototype.template = BH.Templates["credits"];
		CreditsView.prototype.events = {
			"click .close": "closeClicked"
		};
		CreditsView.prototype.initialize = function() {
			this.chromeAPI = chrome;
			return this.attachGeneralEvents()
		};
		CreditsView.prototype.render = function() {
			this.$el.html(this.renderTemplate(this.getI18nValues()));
			return this
		};
		CreditsView.prototype.closeClicked = function(ev) {
			ev.preventDefault();
			return this.close()
		};
		CreditsView.prototype.openClicked = function(ev) {
			ev.preventDefault();
			return this.open()
		};
		CreditsView.prototype.getI18nValues = function() {
			var properties;
			properties = this.t(["credits_title", "translators_heading", "spanish", "swedish", "german", "french", "italian", "hungarian", "chinese_simplified", "arabic", "polish", "portuguese", "russian", "slovak", "catalonian", "hindi", "vietnamese", "japanese", "romanian", "czech", "dutch", "latvian", "turkish", "translation_help_heading", "close_button"]);
			properties["i18n_developed_by"] = this.t("developed_by", ['<a href="http://automagical.posterous.com/">', "</a>", "Roy Kolak"]);
			properties["i18n_translation_instructions"] = this.t("translation_instructions", ["roy.kolak@gmail.com", '<a href="mailto:roy.kolak@gmail.com">', "</a>"]);
			return properties
		};
		return CreditsView
	}(BH.Views.ModalView)
}.call(this);
! function() {
	var __hasProp = {}.hasOwnProperty,
		__extends = function(child, parent) {
			for (var key in parent) {
				if (__hasProp.call(parent, key)) child[key] = parent[key]
			}

			function ctor() {
				this.constructor = child
			}
			ctor.prototype = parent.prototype;
			child.prototype = new ctor;
			child.__super__ = parent.prototype;
			return child
		};
	
}.call(this);
! function() {
	var __hasProp = {}.hasOwnProperty,
		__extends = function(child, parent) {
			for (var key in parent) {
				if (__hasProp.call(parent, key)) child[key] = parent[key]
			}

			function ctor() {
				this.constructor = child
			}
			ctor.prototype = parent.prototype;
			child.prototype = new ctor;
			child.__super__ = parent.prototype;
			return child
		};
	BH.Views.DayResultsView = function(_super) {
		__extends(DayResultsView, _super);

		function DayResultsView() {
			return DayResultsView.__super__.constructor.apply(this, arguments)
		}
		DayResultsView.include(BH.Modules.I18n);
		DayResultsView.prototype.template = BH.Templates["day_results"];
		DayResultsView.prototype.events = {
			"click .delete_visit": "deleteVisitClicked",
			"click .delete_grouped_visit": "deleteGroupedVisitClicked",
			"click .delete_interval": "deleteIntervalClicked",
			"click .show_visits": "toggleGroupedVisitsClicked",
			"click .hide_visits": "toggleGroupedVisitsClicked",
			"click .visit > a": "visitClicked"
		};
		DayResultsView.prototype.initialize = function() {
			return this.chromeAPI = chrome
		};
		DayResultsView.prototype.render = function() {
			var html, properties;
			properties = _.extend(this.getI18nValues(), this.model.toTemplate());
			html = Mustache.to_html(this.template, properties);
			this.$el.html(html);
			return this
		};
		DayResultsView.prototype.visitClicked = function(ev) {
			if ($(ev.target).hasClass("search_domain")) {
				ev.preventDefault();
				return router.navigate($(ev.target).attr("href"), {
					trigger: true
				})
			}
		};
		DayResultsView.prototype.deleteVisitClicked = function(ev) {
			var element, interval, intervalId, _this = this;
			ev.preventDefault();
			element = $(ev.currentTarget).parents("[data-id]").first();
			intervalId = $(ev.currentTarget).parents(".interval").data("id");
			interval = this.model.get("history").get(intervalId);
			return interval.findVisitById($(element).data("id")).destroy({
				success: function() {
					return element.remove()
				}
			})
		};
		DayResultsView.prototype.deleteGroupedVisitClicked = function(ev) {
			ev.preventDefault();
			ev.stopPropagation();
			analyticsTracker.groupedVisitsDeletion();
			$(ev.currentTarget).siblings(".visits").children().each(function(i, visit) {
				return $(visit).find(".delete_visit").trigger("click")
			});
			return $(ev.currentTarget).parents(".visit").remove()
		};
		DayResultsView.prototype.deleteIntervalClicked = function(ev) {
			var visitElements;
			ev.preventDefault();
			analyticsTracker.timeIntervalDeletion();
			visitElements = $(ev.currentTarget).parents(".interval").children(".visits").children();
			return $(visitElements).each(function(i, visit) {
				return setTimeout(function() {
					return $(visit).children(".delete").trigger("click")
				}, i * 10)
			})
		};
		DayResultsView.prototype.toggleGroupedVisitsClicked = function(ev) {
			ev.preventDefault();
			return $(ev.currentTarget).parents(".visit").toggleClass("expanded")
		};
		DayResultsView.prototype.getI18nValues = function() {
			return this.t(["prompt_delete_button", "delete_time_interval_button", "no_visits_found", "expand_button", "collapse_button", "search_by_domain"])
		};
		return DayResultsView
	}(Backbone.View)
}.call(this);
! function() {
	var __hasProp = {}.hasOwnProperty,
		__extends = function(child, parent) {
			for (var key in parent) {
				if (__hasProp.call(parent, key)) child[key] = parent[key]
			}

			function ctor() {
				this.constructor = child
			}
			ctor.prototype = parent.prototype;
			child.prototype = new ctor;
			child.__super__ = parent.prototype;
			return child
		};
	BH.Views.DayView = function(_super) {
		__extends(DayView, _super);

		function DayView() {
			return DayView.__super__.constructor.apply(this, arguments)
		}
		DayView.include(BH.Modules.I18n);
		DayView.prototype.template = BH.Templates["day"];
		DayView.prototype.className = "day_view with_controls";
		DayView.prototype.events = {
			"click .delete_day": "onDeleteAllClicked",
			"click .back_to_week": "onBackToWeekClicked",
			"keyup .search": "onSearchTyped",
			"blur .search": "onSearchBlurred"
		};
		DayView.prototype.initialize = function() {
			this.chromeAPI = chrome;
			this.history = this.options.history;
			return this.history.bind("change", this.onDayHistoryLoaded, this)
		};
		DayView.prototype.render = function() {
			var html, properties;
			properties = _.extend(this.getI18nValues(), this.model.toTemplate());
			html = Mustache.to_html(this.template, properties);
			this.$el.html(html);
			return this
		};
		DayView.prototype.onDayHistoryLoaded = function() {
			this.renderHistory();
			this.assignTabIndices(".interval > .visits > .visit > a:first-child");
			return this.updateDeleteButton()
		};
		DayView.prototype.onDeleteAllClicked = function(ev) {
			return this.promptToDeleteAllVisits()
		};
		DayView.prototype.onBackToWeekClicked = function() {
			return this.$(".content").html("")
		};
		DayView.prototype.pageTitle = function() {
			return this.model.toTemplate().formalDate
		};
		DayView.prototype.renderHistory = function() {
			this.dayResultsView = new BH.Views.DayResultsView({
				model: this.history
			});
			return this.$(".content").html(this.dayResultsView.render().el)
		};
		DayView.prototype.updateDeleteButton = function() {
			var deleteButton;
			deleteButton = this.$("button");
			if (this.history.isEmpty()) {
				return deleteButton.attr("disabled", "disabled")
			} else {
				return deleteButton.removeAttr("disabled")
			}
		};
		DayView.prototype.updateUrl = function() {
			return router.navigate(BH.Lib.Url.week(this.options.weekModel.id))
		};
		DayView.prototype.promptToDeleteAllVisits = function() {
			var promptMessage;
			promptMessage = this.t("confirm_delete_all_visits", [this.model.toTemplate().formalDate]);
			this.promptView = BH.Views.CreatePrompt(promptMessage);
			this.promptView.open();
			return this.promptView.model.on("change", this.promptAction, this)
		};
		DayView.prototype.promptAction = function(prompt) {
			var _this = this;
			if (prompt.get("action")) {
				analyticsTracker.dayVisitsDeletion();
				this.history.destroy();
				return this.history.fetch({
					success: function() {
						return _this.promptView.close()
					}
				})
			} else {
				return this.promptView.close()
			}
		};
		DayView.prototype.getI18nValues = function() {
			var properties;
			properties = this.t(["collapse_button", "expand_button", "delete_all_visits_for_filter_button", "no_visits_found", "search_input_placeholder_text"]);
			properties["i18n_back_to_week_link"] = this.t("back_to_week_link", [this.t("back_arrow")]);
			return properties
		};
		return DayView
	}(BH.Views.MainView)
}.call(this);
! function() {
	var __hasProp = {}.hasOwnProperty,
		__extends = function(child, parent) {
			for (var key in parent) {
				if (__hasProp.call(parent, key)) child[key] = parent[key]
			}

			function ctor() {
				this.constructor = child
			}
			ctor.prototype = parent.prototype;
			child.prototype = new ctor;
			child.__super__ = parent.prototype;
			return child
		};
	BH.Views.MainView = function(_super) {
		__extends(MainView, _super);

		function MainView() {
			return MainView.__super__.constructor.apply(this, arguments)
		}
		MainView.prototype.select = function() {
			var cleanTitle, element, _this = this;
			$(".mainview > *").removeClass("selected");
			$(".mainview > *").css({
				display: "block"
			});
			setTimeout(function() {
				_this.$el.addClass("selected");
				return $(".mainview > *:not(.selected)").css({
					display: "none"
				})
			}, 0);
			if (this.pageTitle) {
				element = $("<div/>");
				cleanTitle = $(element).html(this.pageTitle()).text();
				document.title = "" + cleanTitle + " - Better History"
			}
			this.trigger("selected");
			return this
		};
		MainView.prototype.onSearchTyped = function(ev) {
			var term;
			term = this.trimedSearchTerm();
			if (ev.keyCode === 13 && term !== "") {
				return router.navigate("search/" + term, true)
			}
		};
		MainView.prototype.onSearchBlurred = function() {
			return this.$(".search").val(this.trimedSearchTerm())
		};
		MainView.prototype.trimedSearchTerm = function() {
			return $.trim(this.$(".search").val())
		};
		MainView.prototype.assignTabIndices = function(selector) {
			$("*").removeAttr("tabindex");
			this.$("input.search").attr("tabindex", 1);
			this.$(selector).each(function(i) {
				return $(this).attr("tabindex", i + 2)
			});
			return this.$(".search").focus()
		};
		return MainView
	}(Backbone.View)
}.call(this);
! function() {
	var __hasProp = {}.hasOwnProperty,
		__extends = function(child, parent) {
			for (var key in parent) {
				if (__hasProp.call(parent, key)) child[key] = parent[key]
			}

			function ctor() {
				this.constructor = child
			}
			ctor.prototype = parent.prototype;
			child.prototype = new ctor;
			child.__super__ = parent.prototype;
			return child
		};
	BH.Views.MenuView = function(_super) {
		__extends(MenuView, _super);

		function MenuView() {
			return MenuView.__super__.constructor.apply(this, arguments)
		}
		MenuView.prototype.template = BH.Templates["menu"];
		MenuView.prototype.events = {
			"click .menu > *": "weekClicked"
		};
		MenuView.prototype.render = function() {
			var html;
			html = Mustache.to_html(this.template, this.collection.toTemplate());
			return this.$el.html(html)
		};
		MenuView.prototype.weekClicked = function(ev) {
			var $el;
			this.$(".menu > *").removeClass("selected");
			$el = $(ev.currentTarget);
			$el.addClass("selected");
			return analyticsTracker.weekView($el.data("week-id"), $el.index())
		};
		return MenuView
	}(Backbone.View)
}.call(this);
! function() {
	var __hasProp = {}.hasOwnProperty,
		__extends = function(child, parent) {
			for (var key in parent) {
				if (__hasProp.call(parent, key)) child[key] = parent[key]
			}

			function ctor() {
				this.constructor = child
			}
			ctor.prototype = parent.prototype;
			child.prototype = new ctor;
			child.__super__ = parent.prototype;
			return child
		};
	
}.call(this);
! function() {
	var __hasProp = {}.hasOwnProperty,
		__extends = function(child, parent) {
			for (var key in parent) {
				if (__hasProp.call(parent, key)) child[key] = parent[key]
			}

			function ctor() {
				this.constructor = child
			}
			ctor.prototype = parent.prototype;
			child.prototype = new ctor;
			child.__super__ = parent.prototype;
			return child
		};
	BH.Views.PromptView = function(_super) {
		__extends(PromptView, _super);

		function PromptView() {
			return PromptView.__super__.constructor.apply(this, arguments)
		}
		PromptView.include(BH.Modules.I18n);
		PromptView.prototype.className = "prompt_view";
		PromptView.prototype.template = BH.Templates["prompt"];
		PromptView.prototype.events = {
			"click .no": "clickedNo",
			"click .yes": "clickedYes"
		};
		PromptView.prototype.initialize = function() {
			this.chromeAPI = chrome;
			return this.attachGeneralEvents()
		};
		PromptView.prototype.render = function() {
			this.$el.html(this.renderTemplate(_.extend(this.getI18nValues(), this.model.toTemplate())));
			return this
		};
		PromptView.prototype.clickedNo = function(ev) {
			ev.preventDefault();
			return this.model.set({
				action: false
			})
		};
		PromptView.prototype.clickedYes = function(ev) {
			ev.preventDefault();
			this.spin();
			return this.model.set({
				action: true
			})
		};
		PromptView.prototype.spin = function() {
			return this.$el.addClass("loading")
		};
		PromptView.prototype.getI18nValues = function() {
			return this.t(["prompt_delete_button", "prompt_cancel_button", "prompt_title"])
		};
		return PromptView
	}(BH.Views.ModalView);
	BH.Views.CreatePrompt = function(content) {
		var view;
		view = new BH.Views.PromptView({
			model: new BH.Models.Prompt({
				content: content
			})
		});
		$("body").append(view.render().el);
		return view
	}
}.call(this);
! function() {
	var __hasProp = {}.hasOwnProperty,
		__extends = function(child, parent) {
			for (var key in parent) {
				if (__hasProp.call(parent, key)) child[key] = parent[key]
			}

			function ctor() {
				this.constructor = child
			}
			ctor.prototype = parent.prototype;
			child.prototype = new ctor;
			child.__super__ = parent.prototype;
			return child
		};
	BH.Views.SearchResultsView = function(_super) {
		__extends(SearchResultsView, _super);

		function SearchResultsView() {
			return SearchResultsView.__super__.constructor.apply(this, arguments)
		}
		SearchResultsView.include(BH.Modules.I18n);
		SearchResultsView.prototype.template = BH.Templates["search_results"];
		SearchResultsView.prototype.initialize = function() {
			return this.chromeAPI = chrome
		};
		SearchResultsView.prototype.events = {
			"click .delete_visit": "deleteClicked"
		};
		SearchResultsView.prototype.render = function() {
			var collectionToTemplate, end, highlightedVisits, html, properties, start, visit, _ref;
			_ref = BH.Lib.Pagination.calculateBounds(this.options.page), start = _ref[0], end = _ref[1];
			collectionToTemplate = this.model.toTemplate(start, end);
			highlightedVisits = function() {
				var _i, _len, _ref1, _results;
				_ref1 = collectionToTemplate.visits;
				_results = [];
				for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
					visit = _ref1[_i];
					_results.push(this.markMatches(visit))
				}
				return _results
			}.call(this);
			collectionToTemplate.visits = highlightedVisits;
			properties = _.extend(this.getI18nValues(), collectionToTemplate);
			html = Mustache.to_html(this.template, properties);
			this.$el.html(html);
			return this
		};
		SearchResultsView.prototype.markMatches = function(visit) {
			var locationMatch, regExp, term, timeMatch, titleMatch, _i, _len, _ref;
			regExp = titleMatch = locationMatch = timeMatch = null;
			if (visit != null) {
				_ref = this.model.get("query").split(" ");
				for (_i = 0, _len = _ref.length; _i < _len; _i++) {
					term = _ref[_i];
					regExp = new RegExp(term, "i");
					visit.title = this._wrapMatchInProperty(regExp, visit.title);
					visit.location = this._wrapMatchInProperty(regExp, visit.location);
					visit.time = this._wrapMatchInProperty(regExp, visit.time);
					visit.extendedDate = this._wrapMatchInProperty(regExp, visit.extendedDate)
				}
			}
			return visit
		};
		SearchResultsView.prototype._wrapMatchInProperty = function(regExp, property, match) {
			if (!property) {
				return
			}
			match = property.match(regExp);
			if (match) {
				return property.replace(regExp, '<span class="match">' + match + "</span>")
			} else {
				return property
			}
		};
		SearchResultsView.prototype.deleteClicked = function(ev) {
			var model, _this = this;
			ev.preventDefault();
			model = this._getModelFromElement($(ev.target));
			return model.destroy({
				success: function() {
					return _this._getElementFromModel(model).remove()
				}
			})
		};
		SearchResultsView.prototype._getModelFromElement = function(element) {
			var history;
			history = this.model.get("history");
			return history.get($(element).prev().data("id"))
		};
		SearchResultsView.prototype._getElementFromModel = function(model) {
			return $("[data-id='" + model.id + "']").parents("li")
		};
		SearchResultsView.prototype.getI18nValues = function() {
			return this.t(["no_visits_found"])
		};
		return SearchResultsView
	}(Backbone.View)
}.call(this);
! function() {
	var __hasProp = {}.hasOwnProperty,
		__extends = function(child, parent) {
			for (var key in parent) {
				if (__hasProp.call(parent, key)) child[key] = parent[key]
			}

			function ctor() {
				this.constructor = child
			}
			ctor.prototype = parent.prototype;
			child.prototype = new ctor;
			child.__super__ = parent.prototype;
			return child
		};
	BH.Views.SearchPaginationView = function(_super) {
		__extends(SearchPaginationView, _super);

		function SearchPaginationView() {
			return SearchPaginationView.__super__.constructor.apply(this, arguments)
		}
		SearchPaginationView.include(BH.Modules.I18n);
		SearchPaginationView.include(BH.Modules.Url);
		SearchPaginationView.prototype.className = "search_pagination_view";
		SearchPaginationView.prototype.template = BH.Templates["search_pagination"];
		SearchPaginationView.prototype.initialize = function() {
			this.chromeAPI = chrome;
			this.results = this.options.results;
			this.query = this.options.query;
			this.pages = BH.Lib.Pagination.calculatePages(this.results);
			if (this.model.get("page") > this.pages) {
				return this.model.set({
					page: 1
				})
			}
		};
		SearchPaginationView.prototype.events = {
			"click .pagination a": "onPageClicked"
		};
		SearchPaginationView.prototype.render = function() {
			var html, i, properties;
			properties = {
				paginationClass: this.pages === 1 ? "hidden" : ""
			};
			properties.pages = function() {
				var _i, _ref, _results;
				_results = [];
				for (i = _i = 1, _ref = this.pages; _i <= _ref; i = _i += 1) {
					_results.push({
						url: "" + this.urlFor("search", this.query) + "/p" + i,
						className: i === this.model.get("page") ? "selected" : "",
						number: i
					})
				}
				return _results
			}.call(this);
			properties = _.extend(this.getI18nValues(), properties);
			html = Mustache.to_html(this.template, properties);
			return this.$el.html(html)
		};
		SearchPaginationView.prototype.onPageClicked = function(ev) {
			var $el;
			$el = $(ev.currentTarget);
			analyticsTracker.paginationClick();
			router.navigate($el.attr("href"));
			this.$("a").removeClass("selected");
			$el.addClass("selected");
			return this.model.set({
				page: $el.data("page")
			})
		};
		SearchPaginationView.prototype.getI18nValues = function() {
			var properties;
			properties = [];
			properties["i18n_number_of_visits"] = this.t("number_of_visits", [this.results]);
			return properties
		};
		return SearchPaginationView
	}(BH.Views.MainView)
}.call(this);
! function() {
	var __hasProp = {}.hasOwnProperty,
		__extends = function(child, parent) {
			for (var key in parent) {
				if (__hasProp.call(parent, key)) child[key] = parent[key]
			}

			function ctor() {
				this.constructor = child
			}
			ctor.prototype = parent.prototype;
			child.prototype = new ctor;
			child.__super__ = parent.prototype;
			return child
		};
	BH.Views.SearchView = function(_super) {
		__extends(SearchView, _super);

		function SearchView() {
			return SearchView.__super__.constructor.apply(this, arguments)
		}
		SearchView.include(BH.Modules.I18n);
		SearchView.include(BH.Modules.Url);
		SearchView.prototype.className = "search_view with_controls";
		SearchView.prototype.template = BH.Templates["search"];
		SearchView.prototype.events = {
			"click .delete_all": "clickedDeleteAll",
			"click .corner .delete": "clickedCancelSearch",
			"keyup .search": "onSearchTyped",
			"blur .search": "onSearchBlurred"
		};
		SearchView.prototype.initialize = function() {
			this.chromeAPI = chrome;
			this.history = this.options.history;
			this.page = new Backbone.Model({
				page: 1
			});
			this.history.on("change:history", this.onSearchHistoryChanged, this);
			this.model.on("change:query", this.onQueryChanged, this);
			return this.page.on("change:page", this.renderSearchResults, this)
		};
		SearchView.prototype.render = function() {
			var html, properties, _this = this;
			properties = _.extend(this.getI18nValues(), this.model.toTemplate());
			html = Mustache.to_html(this.template, properties);
			this.$el.append(html);
			if (!this.model.validQuery()) {
				this.$el.addClass("loaded");
				this.$(".title").text(this.t("search_title"));
				this.$(".number_of_results").text("");
				setTimeout(function() {
					return _this.assignTabIndices(".visit a:first-child")
				}, 0)
			}
			this.updateDeleteButton();
			return this
		};
		SearchView.prototype.pageTitle = function() {
			return this.t("searching_title")
		};
		SearchView.prototype.onSearchHistoryChanged = function() {
			this.renderVisits();
			this.assignTabIndices(".visit a:first-child");
			return this.updateDeleteButton()
		};
		SearchView.prototype.onQueryChanged = function() {
			this.updateQueryReferences();
			$(".pagination").html("");
			if (this.model.validQuery()) {
				this.history.set({
					query: this.model.get("query")
				}, {
					silent: true
				});
				return this.$(".corner").addClass("cancelable")
			}
		};
		SearchView.prototype.onPageClicked = function(ev) {
			var $el;
			ev.preventDefault();
			$el = $(ev.currentTarget);
			$(".pagination a").removeClass("selected");
			$el.addClass("selected");
			return this.renderSearchResults()
		};
		SearchView.prototype.updateQueryReferences = function() {
			var page, properties;
			properties = this.model.toTemplate();
			this.$el.removeClass("loaded");
			this.$(".title").text(properties.title);
			this.$(".content").html("");
			page = this.page.get("page") !== 1 ? "/p" + this.page.get("page") : "";
			return router.navigate(this.urlFor("search", properties.query) + page)
		};
		SearchView.prototype.renderVisits = function() {
			var searchPaginationView;
			this.$el.addClass("loaded");
			this.$(".search").focus();
			searchPaginationView = new BH.Views.SearchPaginationView({
				results: this.history.get("history").length,
				query: this.model.get("query"),
				el: $(".pagination"),
				model: this.page
			});
			searchPaginationView.render();
			return this.renderSearchResults()
		};
		SearchView.prototype.renderSearchResults = function() {
			if (this.searchResultsView) {
				this.searchResultsView.undelegateEvents()
			}
			this.searchResultsView = new BH.Views.SearchResultsView({
				model: this.history,
				el: this.$el.children(".content"),
				page: this.page.get("page") - 1
			});
			return this.searchResultsView.render()
		};
		SearchView.prototype.updateDeleteButton = function() {
			var deleteButton;
			deleteButton = this.$(".delete_all");
			if (this.history.isEmpty() || !this.model.validQuery()) {
				return deleteButton.attr("disabled", "disabled")
			} else {
				return deleteButton.removeAttr("disabled")
			}
		};
		SearchView.prototype.clickedCancelSearch = function(ev) {
			ev.preventDefault();
			return router.navigate("search", {
				trigger: true
			})
		};
		SearchView.prototype.clickedDeleteAll = function(ev) {
			ev.preventDefault();
			if ($(ev.target).parent().attr("disabled") !== "disabled") {
				this.promptView = BH.Views.CreatePrompt(this.t("confirm_delete_all_search_results"));
				this.promptView.open();
				return this.promptView.model.on("change", this.deleteAction, this)
			}
		};
		SearchView.prototype.deleteAction = function(prompt) {
			var _this = this;
			if (prompt.get("action")) {
				analyticsTracker.searchResultsDeletion();
				this.history.get("history").destroyAll();
				return this.history.fetch({
					success: function(model) {
						model.trigger("change:history");
						return _this.promptView.close()
					}
				})
			} else {
				return this.promptView.close()
			}
		};
		SearchView.prototype.getI18nValues = function() {
			return this.t(["search_time_frame", "search_input_placeholder_text", "delete_all_visits_for_search_button", "no_visits_found"])
		};
		return SearchView
	}(BH.Views.MainView)
}.call(this);
! function() {
	var __hasProp = {}.hasOwnProperty,
		__extends = function(child, parent) {
			for (var key in parent) {
				if (__hasProp.call(parent, key)) child[key] = parent[key]
			}

			function ctor() {
				this.constructor = child
			}
			ctor.prototype = parent.prototype;
			child.prototype = new ctor;
			child.__super__ = parent.prototype;
			return child
		};
	BH.Views.SettingsView = function(_super) {
		__extends(SettingsView, _super);

		function SettingsView() {
			return SettingsView.__super__.constructor.apply(this, arguments)
		}
		SettingsView.include(BH.Modules.I18n);
		SettingsView.prototype.className = "settings_view";
		SettingsView.prototype.template = BH.Templates["settings"];
		SettingsView.prototype.events = {
			"click .clear_history": "clickedClearHistory",
			"click .credits": "clickedCredits",
			"change #time_grouping": "changedTimeGrouping",
			"change #time_format": "changedTimeFormat",
			"change #open_location": "changedOpenLocation",
			"change #starting_week_day": "changedStartingWeekDay",
			"change #week_day_order": "changedWeekDayOrder",
			"click #domain_grouping": "clickedDomainGrouping",
			"click #search_by_domain": "clickedSearchByDomain",
			"click #search_by_selection": "clickedSearchBySelection"
		};
		SettingsView.prototype.initialize = function() {
			var _this = this;
			this.chromeAPI = chrome;
			this.model.off("change");
			this.model.on("change", function() {
				return _this.model.save()
			}, this.model);
			this.model.on("change:openLocation", this.options.state.updateRoute, this.options.state);
			this.model.on("change:startingWeekDay", this.options.state.updateRoute, this.options.state);
			return this.on("selected", this.activateSocialLinks, this)
		};
		SettingsView.prototype.pageTitle = function() {
			return this.t("settings_title")
		};
		SettingsView.prototype.activateSocialLinks = function() {
			! function(d, s, id) {
				js;
				var fjs, js;
				fjs = d.getElementsByTagName(s)[0];
				if (!d.getElementById(id)) {
					js = d.createElement(s);
					js.id = id;
					js.src = "https://platform.twitter.com/widgets.js";
					return fjs.parentNode.insertBefore(js, fjs)
				}
			}(document, "script", "twitter-wjs");
			window.___gcfg = {
				lang: this.t("google_plus_language")
			};
			return function() {
				var po, s;
				po = document.createElement("script");
				po.type = "text/javascript";
				po.async = true;
				po.src = "https://apis.google.com/js/plusone.js";
				s = document.getElementsByTagName("script")[0];
				return s.parentNode.insertBefore(po, s)
			}()
		};
		SettingsView.prototype.render = function() {
			var html, properties;
			properties = _.extend({}, this.getI18nValues(), this.model.toTemplate());
			html = Mustache.to_html(this.template, properties);
			this.$el.append(html);
			this.populateFields();
			return this
		};
		SettingsView.prototype.populateFields = function() {
			this.$("#open_location").val(this.model.get("openLocation"));
			this.$("#starting_week_day").val(this.model.get("startingWeekDay"));
			this.$("#week_day_order").val(this.model.get("weekDayOrder"));
			this.$("#time_grouping").val(this.model.get("timeGrouping"));
			this.$("#time_format").val(this.model.get("timeFormat"));
			this.$("#domain_grouping").prop("checked", this.model.get("domainGrouping"));
			this.$("#search_by_domain").prop("checked", this.model.get("searchByDomain"));
			return this.$("#search_by_selection").prop("checked", this.model.get("searchBySelection"))
		};
		SettingsView.prototype.changedTimeGrouping = function(ev) {
			return this.model.set({
				timeGrouping: $(ev.currentTarget).val()
			})
		};
		SettingsView.prototype.changedTimeFormat = function(ev) {
			return this.model.set({
				timeFormat: $(ev.currentTarget).val()
			})
		};
		SettingsView.prototype.changedOpenLocation = function(ev) {
			return this.model.set({
				openLocation: $(ev.currentTarget).val()
			})
		};
		SettingsView.prototype.changedStartingWeekDay = function(ev) {
			return this.model.set({
				startingWeekDay: $(ev.currentTarget).val()
			})
		};
		SettingsView.prototype.changedWeekDayOrder = function(ev) {
			return this.model.set({
				weekDayOrder: $(ev.currentTarget).val()
			})
		};
		SettingsView.prototype.clickedDomainGrouping = function(ev) {
			return this.model.set({
				domainGrouping: $(ev.currentTarget).is(":checked")
			})
		};
		SettingsView.prototype.clickedSearchByDomain = function(ev) {
			var backgroundPage, method;
			this.model.set({
				searchByDomain: $(ev.currentTarget).is(":checked")
			});
			backgroundPage = this.chromeAPI.extension.getBackgroundPage();
			method = this.model.get("searchByDomain") ? "create" : "remove";
			return backgroundPage.pageContextMenu[method]()
		};
		SettingsView.prototype.clickedSearchBySelection = function(ev) {
			var backgroundPage, method;
			this.model.set({
				searchBySelection: $(ev.currentTarget).prop("checked")
			});
			backgroundPage = this.chromeAPI.extension.getBackgroundPage();
			method = this.model.get("searchBySelection") ? "create" : "remove";
			return backgroundPage.selectionContextMenu[method]()
		};
		SettingsView.prototype.clickedClearHistory = function(ev) {
			ev.preventDefault();
			return this.chromeAPI.tabs.create({
				url: "chrome://settings/clearBrowserData"
			})
		};
		SettingsView.prototype.clickedCredits = function(ev) {
			var creditsView;
			ev.preventDefault();
			creditsView = new BH.Views.CreditsView;
			$("body").append(creditsView.render().el);
			return creditsView.open()
		};
		SettingsView.prototype.getI18nValues = function() {
			var properties;
			properties = this.t(["settings_title", "clearing_history_section_title", "clear_history_button", "visit_grouping_section_title", "group_visits_by_label", "time_format_label", "group_visits_by_domain_label", "right_click_options_section_title", "search_by_text_selection_label", "search_by_domain_label", "whats_new_section_title", "feedback_section_title", "spread_the_word_section_title", "leave_a_review", "twitter_template", "twitter_language", "open_location", "starting_week_day", "week_day_order", "general_section_title", "mailing_list_link"]);
			properties["i18n_credits_link"] = this.t("credits_link", ["<strong>", "</strong>"]);
			properties["i18n_suggestions_bugs_comments"] = this.t("suggestions_bugs_comments", ['<a href="http://twitter.com/Better_History">', "</a>"]);
			return properties
		};
		return SettingsView
	}(BH.Views.MainView)
}.call(this);
! function() {
	var __hasProp = {}.hasOwnProperty,
		__extends = function(child, parent) {
			for (var key in parent) {
				if (__hasProp.call(parent, key)) child[key] = parent[key]
			}

			function ctor() {
				this.constructor = child
			}
			ctor.prototype = parent.prototype;
			child.prototype = new ctor;
			child.__super__ = parent.prototype;
			return child
		};
	BH.Views.VisitView = function(_super) {
		__extends(VisitView, _super);

		function VisitView() {
			return VisitView.__super__.constructor.apply(this, arguments)
		}
		VisitView.include(BH.Modules.I18n);
		VisitView.prototype.className = "visit_view";
		VisitView.prototype.template = BH.Templates["visit"];
		VisitView.prototype.events = {
			"click .delete_visit": "deleteClicked"
		};
		VisitView.prototype.render = function() {
			var html, properties;
			properties = _.extend(this.getI18nValues(), this.model.toTemplate());
			html = Mustache.to_html(this.template, properties);
			this.$el.html(html);
			return this
		};
		VisitView.prototype.deleteClicked = function(ev) {
			var _this = this;
			ev.preventDefault();
			return this.model.destroy({
				success: function() {
					var method;
					method = _this._isGroupedAndEmpty() ? "_removeGroup" : "_remove";
					return _this[method]()
				}
			})
		};
		VisitView.prototype._remove = function() {
			return this.$el.slideUp("fast", function() {
				return $el.remove()
			})
		};
		VisitView.prototype._removeGroup = function() {
			return $(this._getGroup()).slideUp("fast", function() {
				return $el.remove()
			})
		};
		VisitView.prototype._isGroupedAndEmpty = function() {
			if (this.$el.parents(".expanded").children().length === 1) {
				return true
			} else {
				return false
			}
		};
		VisitView.prototype._getGroup = function() {
			return this.$el.parents(".grouped_visits_view")
		};
		VisitView.prototype.getI18nValues = function() {
			return this.t(["prompt_delete_button"])
		};
		return VisitView
	}(Backbone.View)
}.call(this);
! function() {
	var __hasProp = {}.hasOwnProperty,
		__extends = function(child, parent) {
			for (var key in parent) {
				if (__hasProp.call(parent, key)) child[key] = parent[key]
			}

			function ctor() {
				this.constructor = child
			}
			ctor.prototype = parent.prototype;
			child.prototype = new ctor;
			child.__super__ = parent.prototype;
			return child
		};
	BH.Views.WeekView = function(_super) {
		__extends(WeekView, _super);

		function WeekView() {
			return WeekView.__super__.constructor.apply(this, arguments)
		}
		WeekView.include(BH.Modules.I18n);
		WeekView.prototype.template = BH.Templates["week"];
		WeekView.prototype.className = "week_view with_controls";
		WeekView.prototype.events = {
			"click .delete_all": "onDeleteAllClicked",
			"keyup .search": "onSearchTyped",
			"blur .search": "onSearchBlurred"
		};
		WeekView.prototype.initialize = function() {
			this.chromeAPI = chrome;
			this.history = this.options.history;
			return this.history.bind("change", this.onHistoryLoaded, this)
		};
		WeekView.prototype.render = function() {
			var html, properties;
			properties = _.extend(this.getI18nValues(), this.model.toTemplate());
			html = Mustache.to_html(this.template, properties);
			this.$el.html(html);
			return this
		};
		WeekView.prototype.onHistoryLoaded = function() {
			return this.renderHistory()
		};
		WeekView.prototype.onDeleteAllClicked = function() {
			return this.promptToDeleteAllVisits()
		};
		WeekView.prototype.pageTitle = function() {
			return this.model.toTemplate().title
		};
		WeekView.prototype.renderHistory = function() {
			var container, day, history, _i, _len, _ref;
			history = this.history.toTemplate();
			_ref = history.days;
			for (_i = 0, _len = _ref.length; _i < _len; _i++) {
				day = _ref[_i];
				container = this.$("[data-day=" + day.day + "]");
				container.find(".label .count").html(this.t("number_of_visits", [day.count]));
				container.find(".bar").css({
					width: day.percentage
				})
			}
			this.$(".controls .count").html(this.t("number_of_visits", [history.total]));
			this.assignTabIndices(".day a");
			return this.$el.addClass("loaded")
		};
		WeekView.prototype.promptToDeleteAllVisits = function() {
			var promptMessage;
			promptMessage = this.t("confirm_delete_all_visits", [this.model.toTemplate().title]);
			this.promptView = BH.Views.CreatePrompt(promptMessage);
			this.promptView.open();
			return this.promptView.model.on("change", this.promptAction, this)
		};
		WeekView.prototype.promptAction = function(prompt) {
			if (prompt.get("action")) {
				analyticsTracker.weekVisitsDeletion();
				this.history.destroy();
				this.promptView.close();
				return this.history.fetch()
			} else {
				return this.promptView.close()
			}
		};
		WeekView.prototype.getI18nValues = function() {
			return this.t(["delete_all_visits_for_filter_button", "no_visits_found", "search_input_placeholder_text"])
		};
		return WeekView
	}(BH.Views.MainView)
}.call(this);
! function() {
	var __hasProp = {}.hasOwnProperty,
		__extends = function(child, parent) {
			for (var key in parent) {
				if (__hasProp.call(parent, key)) child[key] = parent[key]
			}

			function ctor() {
				this.constructor = child
			}
			ctor.prototype = parent.prototype;
			child.prototype = new ctor;
			child.__super__ = parent.prototype;
			return child
		};
	BH.Models.History = function(_super) {
		__extends(History, _super);

		function History() {
			return History.__super__.constructor.apply(this, arguments)
		}
		History.prototype.defaults = {
			history: []
		};
		History.prototype.isNew = function() {
			return false
		};
		History.prototype.isEmpty = function() {
			return this.get("history").length === 0
		};
		return History
	}(Backbone.Model)
}.call(this);
! function() {
	var __hasProp = {}.hasOwnProperty,
		__extends = function(child, parent) {
			for (var key in parent) {
				if (__hasProp.call(parent, key)) child[key] = parent[key]
			}

			function ctor() {
				this.constructor = child
			}
			ctor.prototype = parent.prototype;
			child.prototype = new ctor;
			child.__super__ = parent.prototype;
			return child
		};
	BH.Models.Day = function(_super) {
		__extends(Day, _super);

		function Day() {
			return Day.__super__.constructor.apply(this, arguments)
		}
		Day.include(BH.Modules.I18n);
		Day.include(BH.Modules.Url);
		Day.prototype.initialize = function(attrs, options) {
			this.chromeAPI = chrome;
			this.settings = options.settings;
			return this.set({
				id: this.get("date").id()
			})
		};
		Day.prototype.toHistory = function() {
			return {
				date: this.get("date")
			}
		};
		Day.prototype.toTemplate = function() {
			var date, properties, weekId;
			date = this.get("date");
			weekId = this.startingWeekDate().id();
			properties = {
				title: date.format("dddd"),
				formalDate: date.format("LLL"),
				weekUrl: this.urlFor("week", weekId)
			};
			return _.extend(properties, this.toJSON())
		};
		Day.prototype.startingWeekDate = function() {
			return moment(this.get("date")).past(this.settings.get("startingWeekDay"), 0)
		};
		return Day
	}(Backbone.Model)
}.call(this);
! function() {
	var __hasProp = {}.hasOwnProperty,
		__extends = function(child, parent) {
			for (var key in parent) {
				if (__hasProp.call(parent, key)) child[key] = parent[key]
			}

			function ctor() {
				this.constructor = child
			}
			ctor.prototype = parent.prototype;
			child.prototype = new ctor;
			child.__super__ = parent.prototype;
			return child
		};
	BH.Models.DayHistory = function(_super) {
		__extends(DayHistory, _super);

		function DayHistory() {
			return DayHistory.__super__.constructor.apply(this, arguments)
		}
		DayHistory.include(BH.Modules.I18n);
		DayHistory.include(BH.Modules.Worker);
		DayHistory.prototype.initialize = function(attrs, options) {
			this.chromeAPI = chrome;
			this.settings = options.settings;
			return this.historyQuery = new BH.Lib.HistoryQuery(this.chromeAPI)
		};
		DayHistory.prototype.sync = function(method, model, options) {
			var _this = this;
			switch (method) {
				case "read":
					this.set({
						history: [],
						silent: true
					});
					return this.historyQuery.run(this.toChrome(), function(history) {
						return _this.preparse(history, options.success)
					});
				case "delete":
					return this.chromeAPI.history.deleteRange(this.toChrome(false), function() {
						return _this.set({
							history: _this.defaults.history
						})
					})
			}
		};
		DayHistory.prototype.toChrome = function(reading) {
			var properties;
			if (reading == null) {
				reading = true
			}
			properties = {
				startTime: this.sod(),
				endTime: this.eod()
			};
			if (reading) {
				properties.text = ""
			}
			return properties
		};
		DayHistory.prototype.toTemplate = function() {
			return {
				history: this.get("history").map(function(interval) {
					return interval.toTemplate()
				})
			}
		};
		DayHistory.prototype.sod = function() {
			return new Date(this.get("date").sod()).getTime()
		};
		DayHistory.prototype.eod = function() {
			return new Date(this.get("date").eod()).getTime()
		};
		DayHistory.prototype.preparse = function(results, callback) {
			var options, _this = this;
			options = {
				visits: results,
				interval: this.settings.get("timeGrouping")
			};
			return this.worker("timeGrouper", options, function(history) {
				if (_this.settings.get("domainGrouping")) {
					options = {
						intervals: history
					};
					return _this.worker("domainGrouper", options, function(history) {
						return callback(history)
					})
				} else {
					return callback(history)
				}
			})
		};
		DayHistory.prototype.parse = function(data) {
			var interval, intervals, visit, visits, _i, _j, _len, _len1, _ref;
			intervals = new BH.Collections.Intervals;
			for (_i = 0, _len = data.length; _i < _len; _i++) {
				interval = data[_i];
				visits = new BH.Collections.Visits;
				_ref = interval.visits;
				for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) {
					visit = _ref[_j];
					if (_.isArray(visit)) {
						visits.add(new BH.Models.GroupedVisit(visit))
					} else {
						visits.add(new BH.Models.Visit(visit))
					}
				}
				intervals.add({
					id: interval.id,
					datetime: interval.datetime,
					visits: visits
				}, {
					settings: this.settings
				})
			}
			return {
				history: intervals
			}
		};
		return DayHistory
	}(BH.Models.History)
}.call(this);
! function() {
	var __hasProp = {}.hasOwnProperty,
		__extends = function(child, parent) {
			for (var key in parent) {
				if (__hasProp.call(parent, key)) child[key] = parent[key]
			}

			function ctor() {
				this.constructor = child
			}
			ctor.prototype = parent.prototype;
			child.prototype = new ctor;
			child.__super__ = parent.prototype;
			return child
		};
	BH.Models.GroupedVisit = function(_super) {
		__extends(GroupedVisit, _super);

		function GroupedVisit() {
			return GroupedVisit.__super__.constructor.apply(this, arguments)
		}
		GroupedVisit.prototype.initialize = function(attr) {
			this.visits = new BH.Collections.GroupedVisits(attr);
			return this.set({
				host: this.visits.at(0).domain(),
				domain: this.visits.at(0).domain(),
				url: this.visits.at(0).get("url"),
				time: this.visits.at(0).get("time"),
				isGrouped: true,
				visits: this.visits
			})
		};
		GroupedVisit.prototype.toTemplate = function() {
			return _.extend(this.toJSON(), {
				groupedVisits: this.visits.toTemplate()
			})
		};
		return GroupedVisit
	}(Backbone.Model)
}.call(this);
! function() {
	var __hasProp = {}.hasOwnProperty,
		__extends = function(child, parent) {
			for (var key in parent) {
				if (__hasProp.call(parent, key)) child[key] = parent[key]
			}

			function ctor() {
				this.constructor = child
			}
			ctor.prototype = parent.prototype;
			child.prototype = new ctor;
			child.__super__ = parent.prototype;
			return child
		};
	BH.Models.History = function(_super) {
		__extends(History, _super);

		function History() {
			return History.__super__.constructor.apply(this, arguments)
		}
		History.prototype.defaults = {
			history: []
		};
		History.prototype.isNew = function() {
			return false
		};
		History.prototype.isEmpty = function() {
			return this.get("history").length === 0
		};
		return History
	}(Backbone.Model)
}.call(this);
! function() {
	var __hasProp = {}.hasOwnProperty,
		__extends = function(child, parent) {
			for (var key in parent) {
				if (__hasProp.call(parent, key)) child[key] = parent[key]
			}

			function ctor() {
				this.constructor = child
			}
			ctor.prototype = parent.prototype;
			child.prototype = new ctor;
			child.__super__ = parent.prototype;
			return child
		};
	BH.Models.Interval = function(_super) {
		__extends(Interval, _super);

		function Interval() {
			return Interval.__super__.constructor.apply(this, arguments)
		}
		Interval.include(BH.Modules.I18n);
		Interval.prototype.initialize = function(attrs, options) {
			this.chromeAPI = chrome;
			return this.settings = options.settings
		};
		Interval.prototype.toTemplate = function() {
			return _.extend({
				amount: this.t("number_of_visits", [this.get("visits").length.toString(), '<span class="amount">', "</span>"]),
				time: moment(this.get("datetime")).format("LT"),
				id: this.id
			}, this.get("visits").toTemplate())
		};
		Interval.prototype.findVisitById = function(id) {
			var foundVisit, _this = this;
			foundVisit = this.get("visits").get(id);
			if (foundVisit != null) {
				return foundVisit
			}
			this.get("visits").find(function(visit) {
				if (visit.get("visits") != null) {
					foundVisit = visit.get("visits").get(id);
					if (foundVisit != null) {
						return true
					}
				}
			});
			return foundVisit
		};
		return Interval
	}(Backbone.Model)
}.call(this);
! function() {
	var __hasProp = {}.hasOwnProperty,
		__extends = function(child, parent) {
			for (var key in parent) {
				if (__hasProp.call(parent, key)) child[key] = parent[key]
			}

			function ctor() {
				this.constructor = child
			}
			ctor.prototype = parent.prototype;
			child.prototype = new ctor;
			child.__super__ = parent.prototype;
			return child
		};
	BH.Models.Prompt = function(_super) {
		__extends(Prompt, _super);

		function Prompt() {
			return Prompt.__super__.constructor.apply(this, arguments)
		}
		Prompt.prototype.toTemplate = function() {
			return this.toJSON()
		};
		return Prompt
	}(Backbone.Model)
}.call(this);
! function() {
	var __hasProp = {}.hasOwnProperty,
		__extends = function(child, parent) {
			for (var key in parent) {
				if (__hasProp.call(parent, key)) child[key] = parent[key]
			}

			function ctor() {
				this.constructor = child
			}
			ctor.prototype = parent.prototype;
			child.prototype = new ctor;
			child.__super__ = parent.prototype;
			return child
		};
	BH.Models.Search = function(_super) {
		__extends(Search, _super);

		function Search() {
			return Search.__super__.constructor.apply(this, arguments)
		}
		Search.include(BH.Modules.I18n);
		Search.prototype.defaults = function() {
			return {
				query: ""
			}
		};
		Search.prototype.initialize = function() {
			return this.chromeAPI = chrome
		};
		Search.prototype.validQuery = function() {
			return this.get("query") !== ""
		};
		Search.prototype.toHistory = function() {
			return {
				query: this.get("query")
			}
		};
		Search.prototype.toTemplate = function() {
			var i, joined, term, _i, _len, _ref;
			this.terms = this.get("query").split(" ");
			joined = this.t("searching_title") + " ";
			_ref = this.terms;
			for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
				term = _ref[i];
				joined += '"' + term + '"';
				if (i !== this.terms.length - 1) {
					joined += " " + this.t("and") + " "
				}
			}
			return _.extend(this.toJSON(), {
				title: joined
			})
		};
		return Search
	}(Backbone.Model)
}.call(this);
! function() {
	var __hasProp = {}.hasOwnProperty,
		__extends = function(child, parent) {
			for (var key in parent) {
				if (__hasProp.call(parent, key)) child[key] = parent[key]
			}

			function ctor() {
				this.constructor = child
			}
			ctor.prototype = parent.prototype;
			child.prototype = new ctor;
			child.__super__ = parent.prototype;
			return child
		};
	BH.Models.SearchHistory = function(_super) {
		__extends(SearchHistory, _super);

		function SearchHistory() {
			return SearchHistory.__super__.constructor.apply(this, arguments)
		}
		SearchHistory.include(BH.Modules.I18n);
		SearchHistory.prototype.initialize = function() {
			return this.historyQuery = new BH.Lib.HistoryQuery(this.chromeAPI)
		};
		SearchHistory.prototype.sync = function(method, model, options) {
			if (method === "read") {
				return this.historyQuery.run(this.toChrome(), function(history) {
					return options.success(history)
				})
			}
		};
		SearchHistory.prototype.toTemplate = function(start, end) {
			return this.get("history").toTemplate(start, end)
		};
		SearchHistory.prototype.toChrome = function() {
			return {
				text: this.get("query"),
				searching: true
			}
		};
		SearchHistory.prototype.parse = function(data) {
			var visit, visits, _i, _len;
			visits = new BH.Collections.Visits;
			for (_i = 0, _len = data.length; _i < _len; _i++) {
				visit = data[_i];
				visits.add(new BH.Models.Visit(visit))
			}
			return {
				history: visits
			}
		};
		return SearchHistory
	}(BH.Models.History)
}.call(this);
! function() {
	var __hasProp = {}.hasOwnProperty,
		__extends = function(child, parent) {
			for (var key in parent) {
				if (__hasProp.call(parent, key)) child[key] = parent[key]
			}

			function ctor() {
				this.constructor = child
			}
			ctor.prototype = parent.prototype;
			child.prototype = new ctor;
			child.__super__ = parent.prototype;
			return child
		};
	BH.Models.Settings = function(_super) {
		__extends(Settings, _super);

		function Settings() {
			return Settings.__super__.constructor.apply(this, arguments)
		}
		Settings.include(BH.Modules.I18n);
		Settings.prototype.storeName = "settings";
		Settings.prototype.defaults = function() {
			return {
				timeGrouping: 15,
				domainGrouping: true,
				searchByDomain: true,
				searchBySelection: true,
				openLocation: "last_visit",
				startingWeekDay: "Monday",
				weekDayOrder: "ascending"
			}
		};
		Settings.prototype.initialize = function() {
			return this.chromeAPI = chrome
		};
		Settings.prototype.toTemplate = function() {
			var properties, _this = this;
			properties = {
				startingWeekDays: [],
				openLocations: [],
				timeGroupings: [],
				weekDayOrders: [],
				searchBySelection: this.get("searchBySelection"),
				searchByDomain: this.get("searchByDomain"),
				domainGrouping: this.get("domainGrouping")
			};
			_(["monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"]).each(function(day) {
				return properties.startingWeekDays.push({
					text: _this.t(day),
					value: day
				})
			});
			_(["last_visit", "current_day", "current_week"]).each(function(location) {
				return properties.openLocations.push({
					text: _this.t(location),
					value: location
				})
			});
			_(["descending", "ascending"]).each(function(order) {
				return properties.weekDayOrders.push({
					text: _this.t(order),
					value: order
				})
			});
			_([15, 30, 60]).each(function(timeGrouping) {
				return properties.timeGroupings.push({
					text: _this.t("" + timeGrouping + "_minutes_option"),
					value: timeGrouping
				})
			});
			return properties
		};
		return Settings
	}(Backbone.Model)
}.call(this);
! function() {
	var __hasProp = {}.hasOwnProperty,
		__extends = function(child, parent) {
			for (var key in parent) {
				if (__hasProp.call(parent, key)) child[key] = parent[key]
			}

			function ctor() {
				this.constructor = child
			}
			ctor.prototype = parent.prototype;
			child.prototype = new ctor;
			child.__super__ = parent.prototype;
			return child
		};
	BH.Models.State = function(_super) {
		__extends(State, _super);

		function State() {
			return State.__super__.constructor.apply(this, arguments)
		}
		State.include(BH.Modules.I18n);
		State.include(BH.Modules.Url);
		State.prototype.storeName = "state";
		State.prototype.initialize = function(attrs, options) {
			var weekId;
			this.chromeAPI = chrome;
			this.settings = options.settings;
			weekId = this.startingWeekDate().id();
			return this.set({
				route: this.urlFor("week", weekId)
			})
		};
		State.prototype.updateRoute = function() {
			var route, weekId;
			if (this.settings.get("openLocation") === "current_day") {
				route = this.urlFor("day", moment(new Date).id())
			} else if (this.settings.get("openLocation") === "current_week") {
				weekId = this.startingWeekDate().id();
				route = this.urlFor("week", weekId)
			}
			if (route != null) {
				this.set({
					route: route
				})
			}
			return this.save()
		};
		State.prototype.startingWeekDate = function() {
			return moment(new Date).past(this.settings.get("startingWeekDay"), 0)
		};
		return State
	}(Backbone.Model)
}.call(this);
! function() {
	var __hasProp = {}.hasOwnProperty,
		__extends = function(child, parent) {
			for (var key in parent) {
				if (__hasProp.call(parent, key)) child[key] = parent[key]
			}

			function ctor() {
				this.constructor = child
			}
			ctor.prototype = parent.prototype;
			child.prototype = new ctor;
			child.__super__ = parent.prototype;
			return child
		};
	BH.Models.Visit = function(_super) {
		__extends(Visit, _super);

		function Visit() {
			return Visit.__super__.constructor.apply(this, arguments)
		}
		Visit.include(BH.Modules.I18n);
		Visit.prototype.defaults = {
			title: "(No Title)"
		};
		Visit.prototype.initialize = function() {
			this.chromeAPI = chrome;
			this.set({
				id: this.cid
			});
			if (this.get("title") === "") {
				return this.set({
					title: this.defaults.title
				})
			}
		};
		Visit.prototype.sync = function(method, model, options) {
			if (method === "delete") {
				this.chromeAPI.history.deleteUrl({
					url: this.get("url")
				});
				return options.success(this)
			}
		};
		Visit.prototype.toTemplate = function() {
			return _.extend({
				isGrouped: false,
				host: this.domain(),
				path: this.path()
			}, this.toJSON())
		};
		Visit.prototype.domain = function() {
			var match;
			match = this._getDomain(this.get("url"));
			if (match === null) {
				return null
			} else {
				return match[0]
			}
		};
		Visit.prototype.path = function() {
			if (this._getDomain(this.get("url")) != null) {
				return this.get("url").replace(this._getDomain(this.get("url"))[0], "")
			}
		};
		Visit.prototype._getDomain = function(url) {
			return url.match(/\w+:\/\/(.*?)\//)
		};
		return Visit
	}(Backbone.Model)
}.call(this);
! function() {
	var __hasProp = {}.hasOwnProperty,
		__extends = function(child, parent) {
			for (var key in parent) {
				if (__hasProp.call(parent, key)) child[key] = parent[key]
			}

			function ctor() {
				this.constructor = child
			}
			ctor.prototype = parent.prototype;
			child.prototype = new ctor;
			child.__super__ = parent.prototype;
			return child
		};
	BH.Models.Week = function(_super) {
		__extends(Week, _super);

		function Week() {
			return Week.__super__.constructor.apply(this, arguments)
		}
		Week.include(BH.Modules.I18n);
		Week.include(BH.Modules.Url);
		Week.prototype.initialize = function(attrs, options) {
			this.chromeAPI = chrome;
			this.settings = options.settings;
			return this.set({
				id: this.get("date").id()
			})
		};
		Week.prototype.toHistory = function() {
			return {
				startDate: this.get("date"),
				endDate: moment(this.get("date")).add("days", 6)
			}
		};
		Week.prototype.toTemplate = function() {
			var copy, day, days;
			days = function() {
				var _i, _len, _ref, _results;
				_ref = this.inflateDays();
				_results = [];
				for (_i = 0, _len = _ref.length; _i < _len; _i++) {
					day = _ref[_i];
					_results.push({
						day: moment(day.id()).lang("en").format("dddd"),
						title: day.format("dddd"),
						inFuture: moment() < day,
						url: this.urlFor("day", day.id())
					})
				}
				return _results
			}.call(this);
			copy = {
				shortTitle: this.get("date").format("L"),
				url: this.urlFor("week", this.id),
				title: this.t("date_week_label", [this.get("date").format("LL")])
			};
			return _.extend(copy, this.toJSON(), {
				days: days
			})
		};
		Week.prototype.inflateDays = function() {
			var days, i;
			days = function() {
				var _i, _results;
				_results = [];
				for (i = _i = 0; _i <= 6; i = ++_i) {
					_results.push(moment(this.get("date")).add("days", i))
				}
				return _results
			}.call(this);
			if (this.settings.get("weekDayOrder") === "descending") {
				days.reverse()
			}
			return days
		};
		return Week
	}(Backbone.Model)
}.call(this);
! function() {
	var __hasProp = {}.hasOwnProperty,
		__extends = function(child, parent) {
			for (var key in parent) {
				if (__hasProp.call(parent, key)) child[key] = parent[key]
			}

			function ctor() {
				this.constructor = child
			}
			ctor.prototype = parent.prototype;
			child.prototype = new ctor;
			child.__super__ = parent.prototype;
			return child
		};
	BH.Models.WeekHistory = function(_super) {
		__extends(WeekHistory, _super);

		function WeekHistory() {
			return WeekHistory.__super__.constructor.apply(this, arguments)
		}
		WeekHistory.include(BH.Modules.I18n);
		WeekHistory.include(BH.Modules.Worker);
		WeekHistory.prototype.initialize = function() {
			this.chromeAPI = chrome;
			return this.historyQuery = new BH.Lib.HistoryQuery(this.chromeAPI)
		};
		WeekHistory.prototype.sync = function(method, model, options) {
			var _this = this;
			switch (method) {
				case "read":
					return this.historyQuery.run(this.toChrome(), function(results) {
						return _this.preparse(results, options.success)
					});
				case "delete":
					return this.chromeAPI.history.deleteRange(this.toChrome(false), function() {
						return _this.set({
							history: {}
						})
					})
			}
		};
		WeekHistory.prototype.toChrome = function(reading) {
			var properties;
			if (reading == null) {
				reading = true
			}
			properties = {
				startTime: this.sod(),
				endTime: this.eod()
			};
			if (reading) {
				properties.text = ""
			}
			return properties
		};
		WeekHistory.prototype.toTemplate = function() {
			var day, visits;
			return {
				total: this.totalVisits(),
				days: function() {
					var _ref, _results;
					_ref = this.get("history");
					_results = [];
					for (day in _ref) {
						visits = _ref[day];
						_results.push({
							count: visits.length,
							day: day,
							percentage: "" + this.dayVisitPercentage(day) + "%"
						})
					}
					return _results
				}.call(this)
			}
		};
		WeekHistory.prototype.sod = function() {
			return new Date(this.get("startDate").sod()).getTime()
		};
		WeekHistory.prototype.eod = function() {
			return new Date(this.get("endDate").eod()).getTime()
		};
		WeekHistory.prototype.dayVisits = function() {
			var day, visits, _ref, _results;
			_ref = this.get("history");
			_results = [];
			for (day in _ref) {
				visits = _ref[day];
				if (visits != null) {
					_results.push(visits.length)
				} else {
					_results.push(void 0)
				}
			}
			return _results
		};
		WeekHistory.prototype.totalVisits = function() {
			if (this.dayVisits().length === 0) {
				return 0
			}
			return this.dayVisits().reduce(function(sum, num) {
				return sum + num
			})
		};
		WeekHistory.prototype.dayVisitPercentage = function(day) {
			var largest;
			largest = Math.max.apply(Math, this.dayVisits()) || 0;
			if (largest === 0) {
				return 0
			}
			return this.get("history")[day].length / largest * 100
		};
		WeekHistory.prototype.preparse = function(results, callback) {
			return this.worker("dayGrouper", {
				visits: results
			}, function(history) {
				return callback(history)
			})
		};
		WeekHistory.prototype.parse = function(data) {
			return {
				history: data
			}
		};
		return WeekHistory
	}(BH.Models.History)
}.call(this);
! function() {
	var __hasProp = {}.hasOwnProperty,
		__extends = function(child, parent) {
			for (var key in parent) {
				if (__hasProp.call(parent, key)) child[key] = parent[key]
			}

			function ctor() {
				this.constructor = child
			}
			ctor.prototype = parent.prototype;
			child.prototype = new ctor;
			child.__super__ = parent.prototype;
			return child
		};
	BH.Collections.GroupedVisits = function(_super) {
		__extends(GroupedVisits, _super);

		function GroupedVisits() {
			return GroupedVisits.__super__.constructor.apply(this, arguments)
		}
		GroupedVisits.prototype.model = BH.Models.Visit;
		GroupedVisits.prototype.toTemplate = function() {
			var model, _i, _len, _ref, _results;
			_ref = this.models;
			_results = [];
			for (_i = 0, _len = _ref.length; _i < _len; _i++) {
				model = _ref[_i];
				_results.push(model.toTemplate())
			}
			return _results
		};
		return GroupedVisits
	}(Backbone.Collection)
}.call(this);
! function() {
	var __hasProp = {}.hasOwnProperty,
		__extends = function(child, parent) {
			for (var key in parent) {
				if (__hasProp.call(parent, key)) child[key] = parent[key]
			}

			function ctor() {
				this.constructor = child
			}
			ctor.prototype = parent.prototype;
			child.prototype = new ctor;
			child.__super__ = parent.prototype;
			return child
		};
	BH.Collections.Intervals = function(_super) {
		__extends(Intervals, _super);

		function Intervals() {
			return Intervals.__super__.constructor.apply(this, arguments)
		}
		Intervals.prototype.model = BH.Models.Interval;
		Intervals.prototype.toTemplate = function() {
			var intervals, model;
			intervals = function() {
				var _i, _len, _ref, _results;
				_ref = this.models;
				_results = [];
				for (_i = 0, _len = _ref.length; _i < _len; _i++) {
					model = _ref[_i];
					_results.push(model.toTemplate())
				}
				return _results
			}.call(this);
			return {
				intervals: intervals
			}
		};
		Intervals.prototype.destroyAll = function() {
			var _results;
			_results = [];
			while (this.length > 0) {
				if (this.at(0)) {
					_results.push(this.at(0).destroy())
				} else {
					_results.push(void 0)
				}
			}
			return _results
		};
		return Intervals
	}(Backbone.Collection)
}.call(this);
! function() {
	var __hasProp = {}.hasOwnProperty,
		__extends = function(child, parent) {
			for (var key in parent) {
				if (__hasProp.call(parent, key)) child[key] = parent[key]
			}

			function ctor() {
				this.constructor = child
			}
			ctor.prototype = parent.prototype;
			child.prototype = new ctor;
			child.__super__ = parent.prototype;
			return child
		};
	BH.Collections.Visits = function(_super) {
		__extends(Visits, _super);

		function Visits() {
			return Visits.__super__.constructor.apply(this, arguments)
		}
		Visits.prototype.destroyAll = function(options) {
			while (this.length > 0) {
				if (this.at(0)) {
					this.at(0).destroy()
				}
			}
			if (options != null) {
				return options.success()
			}
		};
		Visits.prototype.toTemplate = function(start, end) {
			var i, model, visits, _i, _j, _len, _ref;
			visits = [];
			if (start != null && end != null) {
				for (i = _i = start; start <= end ? _i < end : _i > end; i = start <= end ? ++_i : --_i) {
					if (this.models[i] != null) {
						visits.push(this.models[i].toTemplate())
					}
				}
			} else {
				_ref = this.models;
				for (_j = 0, _len = _ref.length; _j < _len; _j++) {
					model = _ref[_j];
					visits.push(model.toTemplate())
				}
			}
			return {
				visits: visits
			}
		};
		return Visits
	}(Backbone.Collection)
}.call(this);
! function() {
	var __hasProp = {}.hasOwnProperty,
		__extends = function(child, parent) {
			for (var key in parent) {
				if (__hasProp.call(parent, key)) child[key] = parent[key]
			}

			function ctor() {
				this.constructor = child
			}
			ctor.prototype = parent.prototype;
			child.prototype = new ctor;
			child.__super__ = parent.prototype;
			return child
		};
	BH.Collections.Weeks = function(_super) {
		__extends(Weeks, _super);

		function Weeks() {
			return Weeks.__super__.constructor.apply(this, arguments)
		}
		Weeks.include(BH.Modules.I18n);
		Weeks.prototype.model = BH.Models.Week;
		Weeks.prototype.initialize = function(attrs, options) {
			this.chromeAPI = chrome;
			return this.settings = options.settings
		};
		Weeks.prototype.toTemplate = function() {
			var model, weeks;
			weeks = function() {
				var _i, _len, _ref, _results;
				_ref = this.models;
				_results = [];
				for (_i = 0, _len = _ref.length; _i < _len; _i++) {
					model = _ref[_i];
					_results.push(model.toTemplate())
				}
				return _results
			}.call(this);
			return {
				weeks: weeks
			}
		};
		Weeks.prototype.reload = function(startingDay) {
			var i, _i, _len, _ref;
			this.reset();
			_ref = _.range(10);
			for (_i = 0, _len = _ref.length; _i < _len; _i++) {
				i = _ref[_i];
				this.add({
					date: moment(new Date).past(startingDay, i)
				}, {
					settings: this.settings
				})
			}
			return this.trigger("reloaded")
		};
		return Weeks
	}(Backbone.Collection)
}.call(this);
! function() {
	var __hasProp = {}.hasOwnProperty,
		__extends = function(child, parent) {
			for (var key in parent) {
				if (__hasProp.call(parent, key)) child[key] = parent[key]
			}

			function ctor() {
				this.constructor = child
			}
			ctor.prototype = parent.prototype;
			child.prototype = new ctor;
			child.__super__ = parent.prototype;
			return child
		};
	BH.Router = function(_super) {
		__extends(Router, _super);

		function Router() {
			return Router.__super__.constructor.apply(this, arguments)
		}
		Router.prototype.routes = {
			"": "reset",
			"weeks/:id": "week",
			"days/:id": "day",
			settings: "settings",
			"search/*query(/p:page)": "search",
			search: "search"
		};
		Router.prototype.initialize = function(options) {
			var settings, tracker, _this = this;
			settings = options.settings;
			tracker = options.tracker;
			this.state = options.state;
			this.app = new BH.Views.AppView({
				el: $(".app"),
				collection: new BH.Collections.Weeks(null, {
					settings: settings
				}),
				settings: settings,
				state: this.state
			});
			this.app.render();
			this.on("route", function(route) {
				tracker.pageView(Backbone.history.getFragment());
				window.scroll(0, 0);
				if (settings.get("openLocation") === "last_visit") {
					return _this.state.set({
						route: location.hash
					})
				}
			});
			if (location.hash === "") {
				return this.reset
			}
		};
		Router.prototype.reset = function() {
			return this.navigate(this.state.get("route"), {
				trigger: true
			})
		};
		Router.prototype.week = function(id) {
			var view;
			view = this.app.loadWeek(id);
			view.select();
			return this._delay(function() {
				return view.history.fetch()
			})
		};
		Router.prototype.day = function(id) {
			var view;
			view = this.app.loadDay(id);
			view.history.fetch();
			return view.select()
		};
		Router.prototype.settings = function() {
			var view;
			view = this.app.loadSettings();
			return view.select()
		};
		Router.prototype.search = function(query, page) {
			var view;
			if (query == null) {
				query = ""
			}
			view = this.app.loadSearch(query === "" || page ? {
				expired: true
			} : void 0);
			if (page != null) {
				view.page.set({
					page: parseInt(page, 10)
				}, {
					silent: true
				})
			}
			view.model.set({
				query: decodeURIComponent(query)
			});
			view.select();
			return this._delay(function() {
				if (view.model.validQuery()) {
					return view.history.fetch()
				}
			})
		};
		Router.prototype._delay = function(callback) {
			return setTimeout(function() {
				return callback()
			}, 250)
		};
		return Router
	}(Backbone.Router)
}.call(this);
! function() {
	var settings, state, _this = this;
	window.errorTracker = new BH.Trackers.ErrorTracker(Honeybadger);
	window.analyticsTracker = new BH.Trackers.AnalyticsTracker(_gaq);
	try {
		window.syncStore = new BH.Lib.SyncStore({
			chrome: chrome,
			tracker: analyticsTracker
		});
		(new BH.Lib.DateI18n).configure();
		settings = new BH.Models.Settings({});
		state = new BH.Models.State({}, {
			settings: settings
		});
		settings.fetch({
			success: function() {
				return state.fetch({
					success: function() {
						state.updateRoute();
						window.router = new BH.Router({
							settings: settings,
							state: state,
							tracker: analyticsTracker
						});
						return Backbone.history.start()
					}
				})
			}
		});
		syncStore.get(["mailingListPromptTimer", "mailingListPromptSeen"], function(data) {
			var mailingListPromptSeen, mailingListPromptTimer;
			mailingListPromptTimer = data.mailingListPromptTimer || 3;
			mailingListPromptSeen = data.mailingListPromptSeen;
			if (mailingListPromptSeen == null) {
				if (mailingListPromptTimer === 1) {
					(new BH.Views.MailingListView).open();
					syncStore.remove("mailingListPromptTimer");
					syncStore.set({
						mailingListPromptSeen: true
					});
					return analyticsTracker.mailingListPrompt()
				} else {
					return syncStore.set({
						mailingListPromptTimer: mailingListPromptTimer - 1
					})
				}
			}
		})
	} catch (e) {
		errorTracker.report(e)
	}
}.call(this);